1
1
/**
2
- * Tests that a $match with a geo expression still returns the correct results if it has been
3
- * absorbed by a $lookup.
2
+ * Tests that $match stages with a variety of expressions still return the correct results if they
3
+ * have been absorbed by $lookup stages .
4
4
*
5
5
* Accessed collections cannot be implicitly sharded because you cannot $lookup into a sharded
6
6
* collection.
@@ -13,8 +13,16 @@ let testDB = db.getSiblingDB("lookup_absorb_match");
13
13
testDB . dropDatabase ( ) ;
14
14
15
15
let locations = testDB . getCollection ( "locations" ) ;
16
- assert . commandWorked ( locations . insert ( { _id : "doghouse" , coordinates : [ 25.0 , 60.0 ] } ) ) ;
17
- assert . commandWorked ( locations . insert ( { _id : "bullpen" , coordinates : [ - 25.0 , - 60.0 ] } ) ) ;
16
+ assert . commandWorked ( locations . insert ( {
17
+ _id : "doghouse" ,
18
+ coordinates : [ 25.0 , 60.0 ] ,
19
+ extra : { breeds : [ "terrier" , "dachshund" , "bulldog" ] }
20
+ } ) ) ;
21
+ assert . commandWorked ( locations . insert ( {
22
+ _id : "bullpen" ,
23
+ coordinates : [ - 25.0 , - 60.0 ] ,
24
+ extra : { breeds : "Scottish Highland" , feeling : "bullish" }
25
+ } ) ) ;
18
26
19
27
let animals = testDB . getCollection ( "animals" ) ;
20
28
assert . commandWorked ( animals . insert ( { _id : "dog" , locationId : "doghouse" } ) ) ;
@@ -25,32 +33,33 @@ assert.commandWorked(animals.insert({_id: "bull", locationId: "bullpen"}));
25
33
let result = testDB . animals
26
34
. aggregate ( [
27
35
{
28
- $lookup : {
29
- from : "locations" ,
30
- localField : "locationId" ,
31
- foreignField : "_id" ,
32
- as : "location"
33
- }
36
+ $lookup : {
37
+ from : "locations" ,
38
+ localField : "locationId" ,
39
+ foreignField : "_id" ,
40
+ as : "location"
41
+ }
34
42
} ,
35
43
{ $unwind : "$location" } ,
36
44
{
37
- $match : {
38
- "location.coordinates" : {
39
- $geoWithin : {
40
- $geometry : {
41
- type : "MultiPolygon" ,
42
- coordinates : [ [ [
43
- [ 20.0 , 70.0 ] ,
44
- [ 30.0 , 70.0 ] ,
45
- [ 30.0 , 50.0 ] ,
46
- [ 20.0 , 50.0 ] ,
47
- [ 20.0 , 70.0 ]
48
- ] ] ]
49
- }
50
- }
51
- }
52
- }
53
- }
45
+ $match : {
46
+ "location.coordinates" : {
47
+ $geoWithin : {
48
+ $geometry : {
49
+ type : "MultiPolygon" ,
50
+ coordinates : [ [ [
51
+ [ 20.0 , 70.0 ] ,
52
+ [ 30.0 , 70.0 ] ,
53
+ [ 30.0 , 50.0 ] ,
54
+ [ 20.0 , 50.0 ] ,
55
+ [ 20.0 , 70.0 ]
56
+ ] ] ]
57
+ }
58
+ }
59
+ }
60
+ }
61
+ } ,
62
+ { $project : { "location.extra" : false } }
54
63
] )
55
64
. toArray ( ) ;
56
65
let expected =
@@ -61,35 +70,194 @@ assert.eq(result, expected);
61
70
result = testDB . animals
62
71
. aggregate ( [
63
72
{
64
- $lookup : {
65
- from : "locations" ,
66
- localField : "locationId" ,
67
- foreignField : "_id" ,
68
- as : "location"
69
- }
73
+ $lookup : {
74
+ from : "locations" ,
75
+ localField : "locationId" ,
76
+ foreignField : "_id" ,
77
+ as : "location"
78
+ }
70
79
} ,
71
80
{ $unwind : "$location" } ,
72
81
{
73
- $match : {
74
- "location.coordinates" : {
75
- $geoIntersects : {
76
- $geometry : {
77
- type : "MultiPolygon" ,
78
- coordinates : [ [ [
79
- [ - 20.0 , - 70.0 ] ,
80
- [ - 30.0 , - 70.0 ] ,
81
- [ - 30.0 , - 50.0 ] ,
82
- [ - 20.0 , - 50.0 ] ,
83
- [ - 20.0 , - 70.0 ]
84
- ] ] ]
85
- }
86
- }
87
- }
88
- }
89
- }
82
+ $match : {
83
+ "location.coordinates" : {
84
+ $geoIntersects : {
85
+ $geometry : {
86
+ type : "MultiPolygon" ,
87
+ coordinates : [ [ [
88
+ [ - 20.0 , - 70.0 ] ,
89
+ [ - 30.0 , - 70.0 ] ,
90
+ [ - 30.0 , - 50.0 ] ,
91
+ [ - 20.0 , - 50.0 ] ,
92
+ [ - 20.0 , - 70.0 ]
93
+ ] ] ]
94
+ }
95
+ }
96
+ }
97
+ }
98
+ } ,
99
+ { $project : { "location.extra" : false } }
90
100
] )
91
101
. toArray ( ) ;
92
102
expected =
93
103
[ { _id : "bull" , locationId : "bullpen" , location : { _id : "bullpen" , coordinates : [ - 25.0 , - 60.0 ] } } ] ;
94
104
assert . eq ( result , expected ) ;
105
+
106
+ // Test that a $match with $type works as expected when absorbed by a $lookup.
107
+ result = testDB . animals
108
+ . aggregate ( [
109
+ {
110
+ $lookup : {
111
+ from : "locations" ,
112
+ localField : "locationId" ,
113
+ foreignField : "_id" ,
114
+ as : "location"
115
+ }
116
+ } ,
117
+ { $unwind : "$location" } ,
118
+ {
119
+ $match : {
120
+ "location.extra.breeds" : {
121
+ $type : "array"
122
+ }
123
+ }
124
+ } ,
125
+ { $project : { "location.extra" : false } }
126
+ ] )
127
+ . toArray ( ) ;
128
+ expected =
129
+ [ { _id : "dog" , locationId : "doghouse" , location : { _id : "doghouse" , coordinates : [ 25.0 , 60.0 ] } } ] ;
130
+ assert . eq ( result , expected ) ;
131
+
132
+ // Test that a $match with $jsonSchema works as expected although ineligable for absorbtion by a
133
+ // $lookup.
134
+ result = testDB . animals
135
+ . aggregate ( [
136
+ {
137
+ $lookup : {
138
+ from : "locations" ,
139
+ localField : "locationId" ,
140
+ foreignField : "_id" ,
141
+ as : "location"
142
+ }
143
+ } ,
144
+ { $unwind : "$location" } ,
145
+ {
146
+ $match : {
147
+ $jsonSchema : {
148
+ properties : { location : {
149
+ properties : { extra : {
150
+ properties : { breeds : { type : "string" } }
151
+ } }
152
+ } }
153
+ }
154
+ }
155
+ } ,
156
+ { $project : { "location.extra" : false } }
157
+ ] )
158
+ . toArray ( ) ;
159
+ expected =
160
+ [ { _id : "bull" , locationId : "bullpen" , location : { _id : "bullpen" , coordinates : [ - 25.0 , - 60.0 ] } } ] ;
161
+ assert . eq ( result , expected ) ;
162
+
163
+ // Test that a more complex $match with $jsonSchema works as expected although ineligable for
164
+ // absorbtion by a $lookup.
165
+ result = testDB . animals
166
+ . aggregate ( [
167
+ {
168
+ $lookup : {
169
+ from : "locations" ,
170
+ localField : "locationId" ,
171
+ foreignField : "_id" ,
172
+ as : "location"
173
+ }
174
+ } ,
175
+ { $unwind : "$location" } ,
176
+ {
177
+ $match : {
178
+ $jsonSchema : {
179
+ properties : { location : { properties : { extra : { minProperties : 2 } } } }
180
+ }
181
+ }
182
+ } ,
183
+ { $project : { "location.extra" : false } }
184
+ ] )
185
+ . toArray ( ) ;
186
+ expected =
187
+ [ { _id : "bull" , locationId : "bullpen" , location : { _id : "bullpen" , coordinates : [ - 25.0 , - 60.0 ] } } ] ;
188
+ assert . eq ( result , expected ) ;
189
+
190
+ // Test that a $match with $alwaysTrue works as expected although ineligable for absorbtion by a
191
+ // $lookup.
192
+ result = testDB . animals
193
+ . aggregate ( [
194
+ {
195
+ $lookup : {
196
+ from : "locations" ,
197
+ localField : "locationId" ,
198
+ foreignField : "_id" ,
199
+ as : "location"
200
+ }
201
+ } ,
202
+ { $unwind : "$location" } ,
203
+ {
204
+ $match : { $alwaysTrue : 1 }
205
+ } ,
206
+ { $project : { "location.extra" : false } } ,
207
+ { $sort : { _id : 1 } }
208
+ ] )
209
+ . toArray ( ) ;
210
+ expected = [
211
+ { _id : "bull" , locationId : "bullpen" , location : { _id : "bullpen" , coordinates : [ - 25.0 , - 60.0 ] } } ,
212
+ { _id : "dog" , locationId : "doghouse" , location : { _id : "doghouse" , coordinates : [ 25.0 , 60.0 ] } }
213
+ ] ;
214
+ assert . eq ( result , expected ) ;
215
+
216
+ // Test that a $match with $alwaysFalse works as expected although ineligable for absorbtion by a
217
+ // $lookup.
218
+ result = testDB . animals
219
+ . aggregate ( [
220
+ {
221
+ $lookup : {
222
+ from : "locations" ,
223
+ localField : "locationId" ,
224
+ foreignField : "_id" ,
225
+ as : "location"
226
+ }
227
+ } ,
228
+ { $unwind : "$location" } ,
229
+ {
230
+ $match : { $alwaysFalse : 1 }
231
+ } ,
232
+ { $project : { "location.extra" : false } } ,
233
+ ] )
234
+ . toArray ( ) ;
235
+ expected = [ ] ;
236
+ assert . eq ( result , expected ) ;
237
+
238
+ // Test that a $match with $expr works as expected although ineligable for absorbtion by a $lookup.
239
+ result = testDB . animals
240
+ . aggregate ( [
241
+ {
242
+ $lookup : {
243
+ from : "locations" ,
244
+ localField : "locationId" ,
245
+ foreignField : "_id" ,
246
+ as : "location"
247
+ }
248
+ } ,
249
+ { $unwind : "$location" } ,
250
+ {
251
+ $match : {
252
+ $expr : {
253
+ $in : [ 25.0 , "$location.coordinates" ]
254
+ }
255
+ }
256
+ } ,
257
+ { $project : { "location.extra" : false } } ,
258
+ ] )
259
+ . toArray ( ) ;
260
+ expected =
261
+ [ { _id : "dog" , locationId : "doghouse" , location : { _id : "doghouse" , coordinates : [ 25.0 , 60.0 ] } } ] ;
262
+ assert . eq ( result , expected ) ;
95
263
} ( ) ) ;
0 commit comments