@@ -26,25 +26,10 @@ def convert_expr_to_match(self, expr):
26
26
expr_content = expr_query ["$expr" ]
27
27
28
28
# Handle the expression content
29
- match_conditions , remaining_expr_conditions = self ._process_expression (expr_content )
29
+ optimized_query = self ._process_expression (expr_content )
30
30
31
- # If there are remaining conditions that couldn't be optimized,
32
- # keep them in an $expr
33
- if remaining_expr_conditions :
34
- print (f"Remaining conditions: { remaining_expr_conditions } , match_conditions: { match_conditions } " )
35
- if len (remaining_expr_conditions ) == 1 :
36
- expr_conditions = {"$expr" : remaining_expr_conditions [0 ]}
37
- else :
38
- expr_conditions = {"$expr" : {"$and" : remaining_expr_conditions }}
39
-
40
- if match_conditions :
41
- # This assumes match_conditions is a list of dicts with $match
42
- match_conditions [0 ]["$match" ].update (expr_conditions )
43
- else :
44
- match_conditions .append ({"$match" : expr_conditions })
45
-
46
- print (f"Original expr: { expr_query } , optimized expr: { match_conditions } " )
47
- return match_conditions
31
+ # print(f"Original expr:\n{json_util.dumps(expr_query)}\nOptimized expr:\n{json_util.dumps(optimized_query)}")
32
+ return optimized_query
48
33
49
34
def _process_expression (self , expr ):
50
35
"""
@@ -63,32 +48,24 @@ def _process_expression(self, expr):
63
48
# If they fail, they should failover to a remaining conditions list
64
49
# There's probably a better way to do this, but this is a start
65
50
if has_and :
66
- and_match_conditions , and_remaining_conditions = self ._process_logical_conditions (
67
- "$and" , expr ["$and" ]
68
- )
51
+ and_match_conditions = self ._process_logical_conditions ("$and" , expr ["$and" ])
69
52
match_conditions .extend (and_match_conditions )
70
- remaining_conditions .extend (and_remaining_conditions )
71
53
if has_or :
72
- or_match_conditions , or_remaining_conditions = self ._process_logical_conditions (
73
- "$or" , expr ["$or" ]
74
- )
54
+ or_match_conditions = self ._process_logical_conditions ("$or" , expr ["$or" ])
75
55
match_conditions .extend (or_match_conditions )
76
- remaining_conditions .extend (or_remaining_conditions )
77
56
if not has_and and not has_or :
78
57
# Process single condition
79
58
optimized = convert_expression (expr )
80
59
if optimized :
81
60
match_conditions .append ({"$match" : optimized })
82
61
else :
83
- remaining_conditions .append (expr )
62
+ remaining_conditions .append ({ "$match" : { "$ expr" : expr }} )
84
63
else :
85
64
# Can't optimize
86
- remaining_conditions .append (expr )
87
- return match_conditions , remaining_conditions
65
+ remaining_conditions .append ({ "$ expr" : expr } )
66
+ return match_conditions + remaining_conditions
88
67
89
- def _process_logical_conditions (
90
- self , logical_op , logical_conditions
91
- ):
68
+ def _process_logical_conditions (self , logical_op , logical_conditions ):
92
69
"""
93
70
Process conditions within a logical array.
94
71
@@ -99,15 +76,27 @@ def _process_logical_conditions(
99
76
match_conditions = []
100
77
remaining_conditions = []
101
78
for condition in logical_conditions :
79
+ _remaining_conditions = []
102
80
if isinstance (condition , dict ):
103
81
if optimized := convert_expression (condition ):
104
82
optimized_conditions .append (optimized )
105
83
else :
106
- remaining_conditions .append (condition )
84
+ # print(f"Can't optimize condition: {condition}")
85
+ _remaining_conditions .append (condition )
107
86
else :
108
- remaining_conditions .append (condition )
87
+ _remaining_conditions .append (condition )
88
+ if _remaining_conditions :
89
+ # Any expressions we can't optimize must remain in an $expr that preserves the logical operator
90
+ if len (_remaining_conditions ) > 1 :
91
+ remaining_conditions .append ({"$expr" : {logical_op : _remaining_conditions }})
92
+ else :
93
+ remaining_conditions .append ({"$expr" : _remaining_conditions [0 ]})
109
94
if optimized_conditions :
110
- match_conditions .append ({"$match" : {logical_op : optimized_conditions }})
95
+ optimized_conditions .extend (remaining_conditions )
96
+ if len (optimized_conditions ) > 1 :
97
+ match_conditions .append ({"$match" : {logical_op : optimized_conditions }})
98
+ else :
99
+ match_conditions .append ({"$match" : optimized_conditions [0 ]})
111
100
else :
112
- remaining_conditions = [ {logical_op : logical_conditions }]
113
- return match_conditions , remaining_conditions
101
+ match_conditions . append ({ "$match" : {logical_op : remaining_conditions }})
102
+ return match_conditions
0 commit comments