Skip to content

Commit 6e92b2b

Browse files
committed
Edits.
1 parent 2a135cc commit 6e92b2b

File tree

3 files changed

+48
-11
lines changed

3 files changed

+48
-11
lines changed

django_mongodb_backend/compiler.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -670,22 +670,28 @@ def collect_pushable(expr, negated=False):
670670
return {}
671671
if negated:
672672
operator = OR if operator == AND else AND
673-
result = defaultdict(list, next(pushable_expressions, {}))
673+
result = next(pushable_expressions, {})
674674
shared_alias = set(result)
675675
for pe in pushable_expressions:
676676
shared_alias &= set(pe)
677677
for alias, expressions in pe.items():
678-
result[alias] += expressions
678+
children = [expressions]
679+
if alias in result:
680+
children.append(result[alias])
681+
result[alias] = WhereNode(
682+
children=children,
683+
negated=negated,
684+
connector=operator,
685+
)
679686
if operator == AND:
680687
return result
681688
return {k: v for k, v in result.items() if k in shared_alias}
682689
if expr.lhs.is_simple_column and (
683690
is_constant_value(expr.rhs) or expr.rhs.is_simple_column
684691
):
685692
alias = expr.lhs.alias
686-
if negated:
687-
expr = WhereNode(children=[expr], negated=True)
688-
return {expr.lhs.alias: [expr]}
693+
expr = WhereNode(children=[expr], negated=negated)
694+
return {alias: expr}
689695
return {}
690696

691697
return collect_pushable(self.get_where())
@@ -699,7 +705,7 @@ def get_lookup_pipeline(self):
699705
if not self.query.alias_refcount[alias] or self.collection_name == alias:
700706
continue
701707
result += self.query.alias_map[alias].as_mql(
702-
self, self.connection, WhereNode(pushed_filters[alias], connector=AND)
708+
self, self.connection, pushed_filters.get(alias)
703709
)
704710
return result
705711

django_mongodb_backend/test.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,28 @@
66
class MongoTestCaseMixin:
77
maxDiff = None
88

9+
COMMUTATIVE_OPERATORS = {"$and", "$or", "$all"}
10+
11+
@staticmethod
12+
def _normalize_query(obj):
13+
if isinstance(obj, dict):
14+
normalized = {}
15+
for k, v in obj.items():
16+
if k in MongoTestCaseMixin.COMMUTATIVE_OPERATORS and isinstance(v, list):
17+
# Only sort for commutative operators
18+
normalized[k] = sorted(
19+
(MongoTestCaseMixin._normalize_query(i) for i in v), key=lambda x: str(x)
20+
)
21+
else:
22+
normalized[k] = MongoTestCaseMixin._normalize_query(v)
23+
return normalized
24+
25+
if isinstance(obj, list):
26+
# Lists not under commutative ops keep their order
27+
return [MongoTestCaseMixin._normalize_query(i) for i in obj]
28+
29+
return obj
30+
931
def assertAggregateQuery(self, query, expected_collection, expected_pipeline):
1032
"""
1133
Assert that the logged query is equal to:
@@ -16,6 +38,10 @@ def assertAggregateQuery(self, query, expected_collection, expected_pipeline):
1638
self.assertEqual(operator, "aggregate")
1739
self.assertEqual(collection, expected_collection)
1840
self.assertEqual(
19-
eval(pipeline[:-1], {"SON": SON, "ObjectId": ObjectId, "Decimal128": Decimal128}, {}), # noqa: S307
20-
expected_pipeline,
41+
self._normalize_query(
42+
eval( # noqa: S307
43+
pipeline[:-1], {"SON": SON, "ObjectId": ObjectId, "Decimal128": Decimal128}, {}
44+
)
45+
),
46+
self._normalize_query(expected_pipeline),
2147
)

tests/queries_/test_mql.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,6 @@ def test_filter_on_local_and_nested_join_fields(self):
267267
)
268268

269269
def test_negated_related_filter_is_not_pushable(self):
270-
# import ipdb
271-
# ipdb.set_trace()
272270
with self.assertNumQueries(1) as ctx:
273271
list(Book.objects.filter(~models.Q(author__name="John")))
274272
self.assertAggregateQuery(
@@ -283,7 +281,14 @@ def test_negated_related_filter_is_not_pushable(self):
283281
"pipeline": [
284282
{
285283
"$match": {
286-
"$expr": {"$and": [{"$eq": ["$$parent__field__0", "$_id"]}]}
284+
"$and": [
285+
{
286+
"$expr": {
287+
"$and": [{"$eq": ["$$parent__field__0", "$_id"]}]
288+
}
289+
},
290+
{"$nor": [{"name": "John"}]},
291+
]
287292
}
288293
}
289294
],

0 commit comments

Comments
 (0)