Skip to content

Commit a05cae7

Browse files
committed
Port to mongodb version 6
1 parent fa72e1c commit a05cae7

File tree

5 files changed

+83
-41
lines changed

5 files changed

+83
-41
lines changed

django_mongodb_backend/compiler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ def build_query(self, columns=None):
481481
query.lookup_pipeline = self.get_lookup_pipeline()
482482
where = self.get_where()
483483
try:
484-
expr = where.as_mql(self, self.connection) if where else {}
484+
expr = where.as_mql(self, self.connection, as_path=True) if where else {}
485485
except FullResultSet:
486486
query.match_mql = {}
487487
else:

django_mongodb_backend/fields/array.py

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -264,14 +264,21 @@ def as_mql(self, compiler, connection, as_path=False):
264264
return {lhs_mql: {"$all": value}}
265265
lhs_mql = process_lhs(self, compiler, connection, as_path=False)
266266
value = process_rhs(self, compiler, connection, as_path=False)
267+
expr = {
268+
"$and": [
269+
{"$ne": [lhs_mql, None]},
270+
{"$ne": [value, None]},
271+
{"$setIsSubset": [value, lhs_mql]},
272+
]
273+
}
274+
if as_path:
275+
return {"$expr": expr}
267276
return {
268-
"$expr": {
269-
"$and": [
270-
{"$ne": [lhs_mql, None]},
271-
{"$ne": [value, None]},
272-
{"$setIsSubset": [value, lhs_mql]},
273-
]
274-
}
277+
"$and": [
278+
{"$ne": [lhs_mql, None]},
279+
{"$ne": [value, None]},
280+
{"$setIsSubset": [value, lhs_mql]},
281+
]
275282
}
276283

277284

@@ -282,15 +289,16 @@ class ArrayContainedBy(ArrayRHSMixin, FieldGetDbPrepValueMixin, Lookup):
282289
def as_mql(self, compiler, connection, as_path=False):
283290
lhs_mql = process_lhs(self, compiler, connection, as_path=False)
284291
value = process_rhs(self, compiler, connection, as_path=False)
285-
return {
286-
"$expr": {
287-
"$and": [
288-
{"$ne": [lhs_mql, None]},
289-
{"$ne": [value, None]},
290-
{"$setIsSubset": [lhs_mql, value]},
291-
]
292-
}
292+
expr = {
293+
"$and": [
294+
{"$ne": [lhs_mql, None]},
295+
{"$ne": [value, None]},
296+
{"$setIsSubset": [lhs_mql, value]},
297+
]
293298
}
299+
if as_path:
300+
return {"$expr": expr}
301+
return expr
294302

295303

296304
@ArrayField.register_lookup
@@ -345,14 +353,15 @@ def as_mql(self, compiler, connection, as_path=False):
345353

346354
lhs_mql = process_lhs(self, compiler, connection, as_path=False)
347355
value = process_rhs(self, compiler, connection, as_path=False)
348-
return {
349-
"$expr": {
350-
"$and": [
351-
{"$ne": [lhs_mql, None]},
352-
{"$size": {"$setIntersection": [value, lhs_mql]}},
353-
]
354-
}
356+
expr = {
357+
"$and": [
358+
{"$ne": [lhs_mql, None]},
359+
{"$size": {"$setIntersection": [value, lhs_mql]}},
360+
]
355361
}
362+
if as_path:
363+
return {"$expr": expr}
364+
return expr
356365

357366

358367
@ArrayField.register_lookup
@@ -362,7 +371,10 @@ class ArrayLenTransform(Transform):
362371

363372
def as_mql(self, compiler, connection, as_path=False):
364373
lhs_mql = process_lhs(self, compiler, connection, as_path=False)
365-
return {"$cond": {"if": {"$isArray": lhs_mql}, "then": {"$size": lhs_mql}, "else": None}}
374+
expr = {"$cond": {"if": {"$isArray": lhs_mql}, "then": {"$size": lhs_mql}, "else": None}}
375+
if as_path:
376+
return {"$expr": expr}
377+
return expr
366378

367379

368380
@ArrayField.register_lookup

django_mongodb_backend/fields/json.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ def key_transform(self, compiler, connection, as_path=False):
137137
return build_json_mql_path(lhs_mql, key_transforms, as_path=True)
138138
# Collect all key transforms in order.
139139
lhs_mql = previous.as_mql(compiler, connection, as_path=False)
140+
if as_path:
141+
return {"$expr": build_json_mql_path(lhs_mql, key_transforms, as_path=False)}
140142
return build_json_mql_path(lhs_mql, key_transforms, as_path=False)
141143

142144

@@ -157,7 +159,10 @@ def key_transform_in(self, compiler, connection, as_path=False):
157159
value = process_rhs(self, compiler, connection)
158160
# Construct the expression to check if lhs_mql values are in rhs values.
159161
expr = connection.mongo_operators_expr[self.lookup_name](lhs_mql, value)
160-
return {"$expr": {"$and": [_has_key_predicate(lhs_mql, root_column), expr]}}
162+
expr = {"$and": [_has_key_predicate(lhs_mql, root_column), expr]}
163+
if as_path:
164+
return {"$expr": expr}
165+
return expr
161166

162167

163168
def key_transform_is_null(self, compiler, connection, as_path=False):
@@ -179,7 +184,10 @@ def key_transform_is_null(self, compiler, connection, as_path=False):
179184
while isinstance(previous, KeyTransform):
180185
previous = previous.lhs
181186
root_column = previous.as_mql(compiler, connection)
182-
return {"$expr": _has_key_predicate(lhs_mql, root_column, negated=rhs_mql)}
187+
expr = _has_key_predicate(lhs_mql, root_column, negated=rhs_mql)
188+
if as_path:
189+
return {"$expr": expr}
190+
return expr
183191

184192

185193
def key_transform_numeric_lookup_mixin(self, compiler, connection, as_path=False):
@@ -194,7 +202,10 @@ def key_transform_numeric_lookup_mixin(self, compiler, connection, as_path=False
194202
expr = builtin_lookup(self, compiler, connection, as_path=False)
195203
# Check if the type of lhs is not "missing" or "null".
196204
not_missing_or_null = {"$not": {"$in": [{"$type": lhs}, ["missing", "null"]]}}
197-
return {"$expr": {"$and": [expr, not_missing_or_null]}}
205+
expr = {"$and": [expr, not_missing_or_null]}
206+
if as_path:
207+
return {"$expr": expr}
208+
return expr
198209

199210

200211
def key_transform_exact(self, compiler, connection, as_path=False):
@@ -206,6 +217,8 @@ def key_transform_exact(self, compiler, connection, as_path=False):
206217
_has_key_predicate(lhs_mql, None, as_path=True),
207218
]
208219
}
220+
if as_path:
221+
return {"$expr": builtin_lookup(self, compiler, connection, as_path=False)}
209222
return builtin_lookup(self, compiler, connection, as_path=False)
210223

211224

django_mongodb_backend/functions.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
# TEST THAT HAVE THOSE OPERATOR.
7171

7272

73-
def cast(self, compiler, connection, **extra): # noqa: ARG001
73+
def cast(self, compiler, connection, as_path=False): # noqa: ARG001
7474
output_type = connection.data_types[self.output_field.get_internal_type()]
7575
lhs_mql = process_lhs(self, compiler, connection, as_path=False)[0]
7676
if max_length := self.output_field.max_length:
@@ -82,50 +82,63 @@ def cast(self, compiler, connection, **extra): # noqa: ARG001
8282
lhs_mql = {"$convert": {"input": lhs_mql, "to": output_type}}
8383
if decimal_places := getattr(self.output_field, "decimal_places", None):
8484
lhs_mql = {"$trunc": [lhs_mql, decimal_places]}
85+
8586
return lhs_mql
8687

8788

8889
def concat(self, compiler, connection, as_path=False):
8990
return self.get_source_expressions()[0].as_mql(compiler, connection, as_path=as_path)
9091

9192

92-
def concat_pair(self, compiler, connection, as_path=False): # noqa: ARG001
93+
def concat_pair(self, compiler, connection, as_path=False):
9394
# null on either side results in null for expression, wrap with coalesce.
9495
coalesced = self.coalesce()
96+
if as_path:
97+
return {"$expr": super(ConcatPair, coalesced).as_mql(compiler, connection, as_path=False)}
9598
return super(ConcatPair, coalesced).as_mql(compiler, connection, as_path=False)
9699

97100

98-
def cot(self, compiler, connection, as_path=False): # noqa: ARG001
99-
lhs_mql = process_lhs(self, compiler, connection, as_path=False)
101+
def cot(self, compiler, connection, as_path=False):
102+
lhs_mql = process_lhs(self, compiler, connection, as_path=as_path)
103+
if as_path:
104+
return {"$expr": {"$divide": [1, {"$tan": lhs_mql}]}}
100105
return {"$divide": [1, {"$tan": lhs_mql}]}
101106

102107

103-
def extract(self, compiler, connection, **extra): # noqa: ARG001
104-
lhs_mql = process_lhs(self, compiler, connection)
108+
def extract(self, compiler, connection, as_path=False):
109+
lhs_mql = process_lhs(self, compiler, connection, as_path=as_path)
105110
operator = EXTRACT_OPERATORS.get(self.lookup_name)
106111
if operator is None:
107112
raise NotSupportedError(f"{self.__class__.__name__} is not supported.")
108113
if timezone := self.get_tzname():
109114
lhs_mql = {"date": lhs_mql, "timezone": timezone}
110-
return {f"${operator}": lhs_mql}
115+
expr = {f"${operator}": lhs_mql}
116+
if as_path:
117+
return {"$expr": expr}
118+
return expr
111119

112120

113-
def func(self, compiler, connection, **extra): # noqa: ARG001
114-
lhs_mql = process_lhs(self, compiler, connection)
121+
def func(self, compiler, connection, as_path=False):
122+
lhs_mql = process_lhs(self, compiler, connection, as_path=as_path)
115123
if self.function is None:
116124
raise NotSupportedError(f"{self} may need an as_mql() method.")
117125
operator = MONGO_OPERATORS.get(self.__class__, self.function.lower())
126+
if as_path:
127+
return {"$expr": {f"${operator}": lhs_mql}}
118128
return {f"${operator}": lhs_mql}
119129

120130

121131
def left(self, compiler, connection, as_path=False): # noqa: ARG001
122132
return self.get_substr().as_mql(compiler, connection, as_path=False)
123133

124134

125-
def length(self, compiler, connection, as_path=False): # noqa: ARG001
135+
def length(self, compiler, connection, as_path=False):
126136
# Check for null first since $strLenCP only accepts strings.
127137
lhs_mql = process_lhs(self, compiler, connection, as_path=False)
128-
return {"$cond": {"if": {"$eq": [lhs_mql, None]}, "then": None, "else": {"$strLenCP": lhs_mql}}}
138+
expr = {"$cond": {"if": {"$eq": [lhs_mql, None]}, "then": None, "else": {"$strLenCP": lhs_mql}}}
139+
if as_path:
140+
return {"$expr": expr}
141+
return expr
129142

130143

131144
def log(self, compiler, connection, as_path=False): # noqa: ARG001
@@ -139,12 +152,15 @@ def now(self, compiler, connection, as_path=False): # noqa: ARG001
139152
return "$$NOW"
140153

141154

142-
def null_if(self, compiler, connection, as_path=False): # noqa: ARG001
155+
def null_if(self, compiler, connection, as_path=False):
143156
"""Return None if expr1==expr2 else expr1."""
144157
expr1, expr2 = (
145158
expr.as_mql(compiler, connection, as_path=False) for expr in self.get_source_expressions()
146159
)
147-
return {"$cond": {"if": {"$eq": [expr1, expr2]}, "then": None, "else": expr1}}
160+
expr = {"$cond": {"if": {"$eq": [expr1, expr2]}, "then": None, "else": expr1}}
161+
if as_path:
162+
return {"$expr": expr}
163+
return expr
148164

149165

150166
def preserve_null(operator):

django_mongodb_backend/query.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ def get_pipeline(self):
8888
pipeline.extend(query.get_pipeline())
8989
if self.match_mql:
9090
pipeline.append({"$match": self.match_mql})
91+
# pipeline.append({"$match": {"$expr": self.match_mql}})
9192
if self.aggregation_pipeline:
9293
pipeline.extend(self.aggregation_pipeline)
9394
if self.project_fields:
@@ -272,7 +273,7 @@ def _get_reroot_replacements(expression):
272273
return lookup_pipeline
273274

274275

275-
def where_node(self, compiler, connection, as_path=True):
276+
def where_node(self, compiler, connection, as_path=False):
276277
if self.connector == AND:
277278
full_needed, empty_needed = len(self.children), 1
278279
else:

0 commit comments

Comments
 (0)