9
9
10
10
class QueryOptimizerTests (SimpleTestCase ):
11
11
def assertOptimizerEqual (self , input , expected ):
12
- result = QueryOptimizer ().optimize (input )
12
+ result = QueryOptimizer ().convert_expr_to_match (input )
13
13
self .assertEqual (result , expected )
14
14
15
15
def test_multiple_optimizable_conditions (self ):
@@ -22,15 +22,17 @@ def test_multiple_optimizable_conditions(self):
22
22
]
23
23
}
24
24
}
25
- expected = {
26
- "$match" : {
27
- "$and" : [
28
- {"status" : "active" },
29
- {"category" : {"$in" : ["electronics" , "books" ]}},
30
- {"verified" : True },
31
- ]
25
+ expected = [
26
+ {
27
+ "$match" : {
28
+ "$and" : [
29
+ {"status" : "active" },
30
+ {"category" : {"$in" : ["electronics" , "books" ]}},
31
+ {"verified" : True },
32
+ ]
33
+ }
32
34
}
33
- }
35
+ ]
34
36
self .assertOptimizerEqual (expr , expected )
35
37
36
38
def test_mixed_optimizable_and_non_optimizable_conditions (self ):
@@ -43,21 +45,25 @@ def test_mixed_optimizable_and_non_optimizable_conditions(self):
43
45
]
44
46
}
45
47
}
46
- expected = {
47
- "$match" : {
48
- "$and" : [{"status" : "active" }, {"category" : {"$in" : ["electronics" ]}}],
49
- "$expr" : {"$gt" : ["$price" , 100 ]},
48
+ expected = [
49
+ {
50
+ "$match" : {
51
+ "$and" : [{"status" : "active" }, {"category" : {"$in" : ["electronics" ]}}],
52
+ "$expr" : {"$gt" : ["$price" , 100 ]},
53
+ }
50
54
}
51
- }
55
+ ]
52
56
self .assertOptimizerEqual (expr , expected )
53
57
54
58
def test_non_optimizable_condition (self ):
55
59
expr = {"$expr" : {"$gt" : ["$price" , 100 ]}}
56
- expected = {
57
- "$match" : {
58
- "$expr" : {"$gt" : ["$price" , 100 ]},
60
+ expected = [
61
+ {
62
+ "$match" : {
63
+ "$expr" : {"$gt" : ["$price" , 100 ]},
64
+ }
59
65
}
60
- }
66
+ ]
61
67
self .assertOptimizerEqual (expr , expected )
62
68
63
69
def test_nested_logical_conditions (self ):
@@ -70,18 +76,14 @@ def test_nested_logical_conditions(self):
70
76
]
71
77
}
72
78
}
73
- expected = {
74
- "$match" : {
75
- "$or" : [
76
- {"status" : "active" },
77
- {"category" : {"$in" : ["electronics" , "books" ]}},
78
- ],
79
- "$and" : [
80
- {"verified" : True },
81
- {"price" : {"$gt" : 50 }},
82
- ],
79
+ expected = [
80
+ {
81
+ "$match" : {
82
+ "$expr" : {"$and" : [{"$eq" : ["$verified" , True ]}, {"$gt" : ["$price" , 50 ]}]},
83
+ "$or" : [{"status" : "active" }, {"category" : {"$in" : ["electronics" , "books" ]}}],
84
+ }
83
85
}
84
- }
86
+ ]
85
87
self .assertOptimizerEqual (expr , expected )
86
88
87
89
def test_complex_nested_with_non_optimizable_parts (self ):
@@ -100,30 +102,32 @@ def test_complex_nested_with_non_optimizable_parts(self):
100
102
]
101
103
}
102
104
}
103
- expected = {
104
- "$match" : {
105
- "$and" : [
106
- {"category" : {"$in" : ["electronics" , "books" ]}},
107
- {"verified" : True },
108
- ],
109
- "$expr" : {
105
+ expected = [
106
+ {
107
+ "$match" : {
110
108
"$and" : [
111
- {
112
- "$or" : [
113
- {"$eq" : ["$status" , "active" ]},
114
- {"$gt" : ["$views" , 1000 ]},
115
- ]
116
- },
117
- {"$gt" : ["$price" , 50 ]},
118
- ]
119
- },
109
+ {"category" : {"$in" : ["electronics" , "books" ]}},
110
+ {"verified" : True },
111
+ ],
112
+ "$expr" : {
113
+ "$and" : [
114
+ {
115
+ "$or" : [
116
+ {"$eq" : ["$status" , "active" ]},
117
+ {"$gt" : ["$views" , 1000 ]},
118
+ ]
119
+ },
120
+ {"$gt" : ["$price" , 50 ]},
121
+ ]
122
+ },
123
+ }
120
124
}
121
- }
125
+ ]
122
126
self .assertOptimizerEqual (expr , expected )
123
127
124
128
def test_london_in_case (self ):
125
129
expr = {"$expr" : {"$in" : ["$author_city" , ["London" ]]}}
126
- expected = {"$match" : {"author_city" : {"$in" : ["London" ]}}}
130
+ expected = [ {"$match" : {"author_city" : {"$in" : ["London" ]}}}]
127
131
self .assertOptimizerEqual (expr , expected )
128
132
129
133
def test_deeply_nested_logical_operators (self ):
@@ -145,24 +149,26 @@ def test_deeply_nested_logical_operators(self):
145
149
]
146
150
}
147
151
}
148
- expected = {
149
- "$match" : {
150
- "$and" : [
151
- {
152
- "$or" : [
153
- {"type" : "premium" },
154
- {
155
- "$and" : [
156
- {"type" : "standard" },
157
- {"region" : {"$in" : ["US" , "CA" ]}},
158
- ]
159
- },
160
- ]
161
- },
162
- {"active" : True },
163
- ]
152
+ expected = [
153
+ {
154
+ "$match" : {
155
+ "$and" : [
156
+ {
157
+ "$or" : [
158
+ {"type" : "premium" },
159
+ {
160
+ "$and" : [
161
+ {"type" : "standard" },
162
+ {"region" : {"$in" : ["US" , "CA" ]}},
163
+ ]
164
+ },
165
+ ]
166
+ },
167
+ {"active" : True },
168
+ ]
169
+ }
164
170
}
165
- }
171
+ ]
166
172
self .assertOptimizerEqual (expr , expected )
167
173
168
174
def test_deeply_nested_logical_operator_with_variable (self ):
@@ -185,22 +191,24 @@ def test_deeply_nested_logical_operator_with_variable(self):
185
191
]
186
192
}
187
193
}
188
- expected = {
189
- "$match" : {
190
- "$expr" : {
191
- "$and" : [
192
- {"$eq" : ["$type" , "premium" ]},
193
- {
194
- "$and" : [
195
- {"$eq" : ["$type" , "$$standard" ]},
196
- {"$in" : ["$region" , ["US" , "CA" ]]},
197
- ]
198
- },
199
- ]
200
- },
201
- "$and" : [{"active" : True }],
194
+ expected = [
195
+ {
196
+ "$match" : {
197
+ "$expr" : {
198
+ "$or" : [
199
+ {"$eq" : ["$type" , "premium" ]},
200
+ {
201
+ "$and" : [
202
+ {"$eq" : ["$type" , "$$standard" ]},
203
+ {"$in" : ["$region" , ["US" , "CA" ]]},
204
+ ]
205
+ },
206
+ ]
207
+ },
208
+ "$and" : [{"active" : True }],
209
+ }
202
210
}
203
- }
211
+ ]
204
212
self .assertOptimizerEqual (expr , expected )
205
213
206
214
@@ -210,23 +218,24 @@ def test_in_query(self):
210
218
list (Author .objects .filter (author_city__in = ["London" ]))
211
219
query = ctx .captured_queries [0 ]["sql" ]
212
220
expected = (
213
- "db.queries__author.aggregate([{'$match': {'author_city': {'$in': ['London']}}}])"
221
+ "db.expression_converter__author.aggregate([{'$match': "
222
+ + "{'author_city': {'$in': ('London',)}}}])"
214
223
)
215
224
self .assertEqual (query , expected )
216
225
217
226
def test_eq_query (self ):
218
227
with self .assertNumQueries (1 ) as ctx :
219
228
list (Author .objects .filter (name = "Alice" ))
220
229
query = ctx .captured_queries [0 ]["sql" ]
221
- expected = "db.queries__author .aggregate([{'$match': {'name': 'Alice'}}])"
230
+ expected = "db.expression_converter__author .aggregate([{'$match': {'name': 'Alice'}}])"
222
231
self .assertEqual (query , expected )
223
232
224
233
def test_eq_and_in_query (self ):
225
234
with self .assertNumQueries (1 ) as ctx :
226
235
list (Author .objects .filter (name = "Alice" , author_city__in = ["London" , "New York" ]))
227
236
query = ctx .captured_queries [0 ]["sql" ]
228
237
expected = (
229
- "db.queries__author .aggregate([{'$match': {'$and': [{'name': 'Alice'}, "
230
- " {'author_city': {'$in': [ 'London', 'New York']} }]}}])"
238
+ "db.expression_converter__author .aggregate([{'$match': {'$and': "
239
+ + "[ {'author_city': {'$in': ( 'London', 'New York')}}, {'name': 'Alice' }]}}])"
231
240
)
232
241
self .assertEqual (query , expected )
0 commit comments