Skip to content

Commit f9a69cc

Browse files
committed
WIP
1 parent 4c3e891 commit f9a69cc

File tree

2 files changed

+30
-14
lines changed

2 files changed

+30
-14
lines changed

django_mongodb_backend/query.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import pprint
12
from functools import reduce, wraps
23
from operator import add as add_operator
34

@@ -90,7 +91,13 @@ def get_pipeline(self):
9091
for query in self.subqueries or ():
9192
pipeline.extend(query.get_pipeline())
9293
if self.match_mql:
94+
optimized = self.query_optimizer.convert_expr_to_match(self.match_mql)
95+
if any("$and" in str(cond) for cond in optimized) and not "$and" in str(self.match_mql["$expr"]):
96+
print(f"$AND MISMATCH MQL\nOptimized:\n\t{pprint.pformat(optimized)}\nOriginal:\n\t{self.match_mql}")
97+
if any("$or" in str(cond) for cond in optimized) and not "$or" in str(self.match_mql["$expr"]):
98+
print(f"$OR MISMATCH MQL\nOptimized:\n\t{pprint.pformat(optimized)}\nOriginal:\n\t{self.match_mql}")
9399
pipeline.extend(self.query_optimizer.convert_expr_to_match(self.match_mql))
100+
# pipeline.append({"$match": self.match_mql})
94101
if self.aggregation_pipeline:
95102
pipeline.extend(self.aggregation_pipeline)
96103
if self.project_fields:

django_mongodb_backend/query_conversion/query_optimizer.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,14 @@ def convert_expr_to_match(self, expr):
2424
return [{"$match": {}}]
2525

2626
expr_content = expr_query["$expr"]
27-
match_conditions = []
28-
remaining_expr_conditions = []
2927

3028
# Handle the expression content
31-
self._process_expression(expr_content, match_conditions, remaining_expr_conditions)
29+
match_conditions, remaining_expr_conditions = self._process_expression(expr_content)
3230

3331
# If there are remaining conditions that couldn't be optimized,
3432
# keep them in an $expr
3533
if remaining_expr_conditions:
34+
print(f"Remaining conditions: {remaining_expr_conditions}, match_conditions: {match_conditions}")
3635
if len(remaining_expr_conditions) == 1:
3736
expr_conditions = {"$expr": remaining_expr_conditions[0]}
3837
else:
@@ -44,17 +43,18 @@ def convert_expr_to_match(self, expr):
4443
else:
4544
match_conditions.append({"$match": expr_conditions})
4645

46+
print(f"Original expr: {expr_query}, optimized expr: {match_conditions}")
4747
return match_conditions
4848

49-
def _process_expression(self, expr, match_conditions, remaining_conditions):
49+
def _process_expression(self, expr):
5050
"""
5151
Process an expression and extract optimizable conditions.
5252
5353
Args:
5454
expr: The expression to process
55-
match_conditions: List to append optimized match conditions
56-
remaining_conditions: List to append non-optimizable conditions
5755
"""
56+
match_conditions = []
57+
remaining_conditions = []
5858
if isinstance(expr, dict):
5959
# Check if this is an $and operation
6060
has_and = "$and" in expr
@@ -63,13 +63,17 @@ def _process_expression(self, expr, match_conditions, remaining_conditions):
6363
# If they fail, they should failover to a remaining conditions list
6464
# There's probably a better way to do this, but this is a start
6565
if has_and:
66-
self._process_logical_conditions(
67-
"$and", expr["$and"], match_conditions, remaining_conditions
66+
and_match_conditions, and_remaining_conditions = self._process_logical_conditions(
67+
"$and", expr["$and"]
6868
)
69+
match_conditions.extend(and_match_conditions)
70+
remaining_conditions.extend(and_remaining_conditions)
6971
if has_or:
70-
self._process_logical_conditions(
71-
"$or", expr["$or"], match_conditions, remaining_conditions
72+
or_match_conditions, or_remaining_conditions = self._process_logical_conditions(
73+
"$or", expr["$or"]
7274
)
75+
match_conditions.extend(or_match_conditions)
76+
remaining_conditions.extend(or_remaining_conditions)
7377
if not has_and and not has_or:
7478
# Process single condition
7579
optimized = convert_expression(expr)
@@ -80,19 +84,20 @@ def _process_expression(self, expr, match_conditions, remaining_conditions):
8084
else:
8185
# Can't optimize
8286
remaining_conditions.append(expr)
87+
return match_conditions, remaining_conditions
8388

8489
def _process_logical_conditions(
85-
self, logical_op, logical_conditions, match_conditions, remaining_conditions
90+
self, logical_op, logical_conditions
8691
):
8792
"""
8893
Process conditions within a logical array.
8994
9095
Args:
9196
logical_conditions: List of conditions within logical operator
92-
match_conditions: List to append optimized match conditions
93-
remaining_conditions: List to append non-optimizable conditions
9497
"""
9598
optimized_conditions = []
99+
match_conditions = []
100+
remaining_conditions = []
96101
for condition in logical_conditions:
97102
if isinstance(condition, dict):
98103
if optimized := convert_expression(condition):
@@ -101,4 +106,8 @@ def _process_logical_conditions(
101106
remaining_conditions.append(condition)
102107
else:
103108
remaining_conditions.append(condition)
104-
match_conditions.append({"$match": {logical_op: optimized_conditions}})
109+
if optimized_conditions:
110+
match_conditions.append({"$match": {logical_op: optimized_conditions}})
111+
else:
112+
remaining_conditions = [{logical_op: logical_conditions}]
113+
return match_conditions, remaining_conditions

0 commit comments

Comments
 (0)