20
20
from .features import DatabaseFeatures
21
21
from .introspection import DatabaseIntrospection
22
22
from .operations import DatabaseOperations
23
- from .query_utils import regex_match
23
+ from .query_utils import regex_expr , regex_match
24
24
from .schema import DatabaseSchemaEditor
25
25
from .utils import OperationDebugWrapper
26
26
from .validation import DatabaseValidation
@@ -108,7 +108,12 @@ def _isnull_operator(a, b):
108
108
}
109
109
return is_null if b else {"$not" : is_null }
110
110
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 = {
112
117
"exact" : lambda a , b : {"$eq" : [a , b ]},
113
118
"gt" : lambda a , b : {"$gt" : [a , b ]},
114
119
"gte" : lambda a , b : {"$gte" : [a , b ]},
@@ -126,6 +131,37 @@ def _isnull_operator(a, b):
126
131
{"$or" : [DatabaseWrapper ._isnull_operator (b [1 ], True ), {"$lte" : [a , b [1 ]]}]},
127
132
]
128
133
},
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
+ },
129
165
"iexact" : lambda a , b : regex_match (a , ("^" , b , {"$literal" : "$" }), insensitive = True ),
130
166
"startswith" : lambda a , b : regex_match (a , ("^" , b )),
131
167
"istartswith" : lambda a , b : regex_match (a , ("^" , b ), insensitive = True ),
0 commit comments