2020from .features import DatabaseFeatures
2121from .introspection import DatabaseIntrospection
2222from .operations import DatabaseOperations
23- from .query_utils import regex_match
23+ from .query_utils import regex_expr , regex_match
2424from .schema import DatabaseSchemaEditor
2525from .utils import OperationDebugWrapper
2626from .validation import DatabaseValidation
@@ -108,7 +108,12 @@ def _isnull_operator(a, b):
108108 }
109109 return is_null if b else {"$not" : is_null }
110110
111- mongo_operators = {
111+ def _isnull_operator_match (a , b ):
112+ if b :
113+ return {"$or" : [{a : {"$exists" : False }}, {a : None }]}
114+ return {"$and" : [{a : {"$exists" : True }}, {a : {"$ne" : None }}]}
115+
116+ mongo_operators_expr = {
112117 "exact" : lambda a , b : {"$eq" : [a , b ]},
113118 "gt" : lambda a , b : {"$gt" : [a , b ]},
114119 "gte" : lambda a , b : {"$gte" : [a , b ]},
@@ -126,6 +131,37 @@ def _isnull_operator(a, b):
126131 {"$or" : [DatabaseWrapper ._isnull_operator (b [1 ], True ), {"$lte" : [a , b [1 ]]}]},
127132 ]
128133 },
134+ "iexact" : lambda a , b : regex_expr (a , ("^" , b , {"$literal" : "$" }), insensitive = True ),
135+ "startswith" : lambda a , b : regex_expr (a , ("^" , b )),
136+ "istartswith" : lambda a , b : regex_expr (a , ("^" , b ), insensitive = True ),
137+ "endswith" : lambda a , b : regex_expr (a , (b , {"$literal" : "$" })),
138+ "iendswith" : lambda a , b : regex_expr (a , (b , {"$literal" : "$" }), insensitive = True ),
139+ "contains" : lambda a , b : regex_expr (a , b ),
140+ "icontains" : lambda a , b : regex_expr (a , b , insensitive = True ),
141+ "regex" : lambda a , b : regex_expr (a , b ),
142+ "iregex" : lambda a , b : regex_expr (a , b , insensitive = True ),
143+ }
144+
145+ mongo_operators_match = {
146+ "exact" : lambda a , b : {a : b },
147+ "gt" : lambda a , b : {a : {"$gt" : b }},
148+ "gte" : lambda a , b : {a : {"$gte" : b }},
149+ # MongoDB considers null less than zero. Exclude null values to match
150+ # SQL behavior.
151+ "lt" : lambda a , b : {
152+ "$and" : [{a : {"$lt" : b }}, DatabaseWrapper ._isnull_operator_match (a , False )]
153+ },
154+ "lte" : lambda a , b : {
155+ "$and" : [{a : {"$lte" : b }}, DatabaseWrapper ._isnull_operator_match (a , False )]
156+ },
157+ "in" : lambda a , b : {a : {"$in" : list (b )}},
158+ "isnull" : _isnull_operator_match ,
159+ "range" : lambda a , b : {
160+ "$and" : [
161+ {"$or" : [DatabaseWrapper ._isnull_operator_match (b [0 ], True ), {a : {"$gte" : b [0 ]}}]},
162+ {"$or" : [DatabaseWrapper ._isnull_operator_match (b [1 ], True ), {a : {"$lte" : b [1 ]}}]},
163+ ]
164+ },
129165 "iexact" : lambda a , b : regex_match (a , ("^" , b , {"$literal" : "$" }), insensitive = True ),
130166 "startswith" : lambda a , b : regex_match (a , ("^" , b )),
131167 "istartswith" : lambda a , b : regex_match (a , ("^" , b ), insensitive = True ),
0 commit comments