@@ -123,50 +123,68 @@ TEST(CanonicalQueryEncoderTest, ComputeKey) {
123123 // With sort
124124 testComputeKey (" {}" , " {a: 1}" , " {}" , " an~aa" );
125125 testComputeKey (" {}" , " {a: -1}" , " {}" , " an~da" );
126- testComputeKey (" {}" ,
127- " {a: {$meta: 'textScore'}}" ,
128- " {a: {$meta: 'textScore'}}" ,
129- " an~ta|{ $meta: \" textScore\" }a" );
126+ testComputeKey (" {}" , " {a: {$meta: 'textScore'}}" , " {a: {$meta: 'textScore'}}" , " an~ta" );
130127 testComputeKey (" {a: 1}" , " {b: 1}" , " {}" , " eqa~ab" );
131128
132129 // With projection
133- testComputeKey (" {}" , " {}" , " {a: 1}" , " an|ia" );
134- testComputeKey (" {}" , " {}" , " {a: -1}" , " an|ia" );
135- testComputeKey (" {}" , " {}" , " {a: -1.0}" , " an|ia" );
136- testComputeKey (" {}" , " {}" , " {a: true}" , " an|ia" );
137- testComputeKey (" {}" , " {}" , " {a: 0}" , " an|ea" );
138- testComputeKey (" {}" , " {}" , " {a: false}" , " an|ea" );
139- testComputeKey (" {}" , " {}" , " {a: 99}" , " an|ia" );
140- testComputeKey (" {}" , " {}" , " {a: 'foo'}" , " an|ia" );
141- testComputeKey (" {}" , " {}" , " {a: {$slice: [3, 5]}}" , " an|{ $slice: \\ [ 3\\ , 5 \\ ] }a" );
142- testComputeKey (" {}" , " {}" , " {a: {$elemMatch: {x: 2}}}" , " an|{ $elemMatch: { x: 2 } }a" );
143- testComputeKey (" {}" , " {}" , " {a: ObjectId('507f191e810c19729de860ea')}" , " an|ia" );
144- testComputeKey (" {a: 1}" , " {}" , " {'a.$': 1}" , " eqa|ia.$" );
145- testComputeKey (" {a: 1}" , " {}" , " {a: 1}" , " eqa|ia" );
130+ testComputeKey (" {}" , " {}" , " {a: 1}" , " an|_id-a" );
131+ testComputeKey (" {}" , " {}" , " {a: -1}" , " an|_id-a" );
132+ testComputeKey (" {}" , " {}" , " {a: -1.0}" , " an|_id-a" );
133+ testComputeKey (" {}" , " {}" , " {a: true}" , " an|_id-a" );
134+ testComputeKey (" {}" , " {}" , " {a: 0}" , " an" );
135+ testComputeKey (" {}" , " {}" , " {a: false}" , " an" );
136+ testComputeKey (" {}" , " {}" , " {a: 99}" , " an|_id-a" );
137+ testComputeKey (" {}" , " {}" , " {a: 'foo'}" , " an|_id-a" );
138+ // $slice defaults to exclusion.
139+ testComputeKey (" {}" , " {}" , " {a: {$slice: [3, 5]}}" , " an" );
140+ testComputeKey (" {}" , " {}" , " {a: {$slice: [3, 5]}, b: 0}" , " an" );
141+
142+ // But even when using $slice in an inclusion, the entire document is needed.
143+ testComputeKey (" {}" , " {}" , " {a: {$slice: [3, 5]}, b: 1}" , " an" );
144+
145+ testComputeKey (" {}" , " {}" , " {a: {$elemMatch: {x: 2}}}" , " an" );
146+ testComputeKey (" {}" , " {}" , " {a: {$elemMatch: {x: 2}}, b: 0}" , " an" );
147+ testComputeKey (" {}" , " {}" , " {a: {$elemMatch: {x: 2}}, b: 1}" , " an" );
148+
149+ testComputeKey (" {}" , " {}" , " {a: {$slice: [3, 5]}, b: {$elemMatch: {x: 2}}}" , " an" );
150+
151+ testComputeKey (" {}" , " {}" , " {a: ObjectId('507f191e810c19729de860ea')}" , " an|_id-a" );
152+ testComputeKey (" {a: 1}" , " {}" , " {'a.$': 1}" , " eqa" );
153+ testComputeKey (" {a: 1}" , " {}" , " {a: 1}" , " eqa|_id-a" );
146154
147155 // Projection should be order-insensitive
148- testComputeKey (" {}" , " {}" , " {a: 1, b: 1}" , " an|iaib" );
149- testComputeKey (" {}" , " {}" , " {b: 1, a: 1}" , " an|iaib" );
156+ testComputeKey (" {}" , " {}" , " {a: 1, b: 1}" , " an|_id-a-b" );
157+ testComputeKey (" {}" , " {}" , " {b: 1, a: 1}" , " an|_id-a-b" );
158+
159+ // And should escape the separation character.
160+ testComputeKey (" {}" , " {}" , " {'b-1': 1, 'a-2': 1}" , " an|_id-a\\ -2-b\\ -1" );
161+
162+ // And should exclude $-prefixed fields which can be added internally.
163+ testComputeKey (" {}" , " {x: 1}" , " {$sortKey: {$meta: 'sortKey'}}" , " an~ax" );
164+ testComputeKey (" {}" , " {}" , " {}" , " an" );
165+
166+ testComputeKey (" {}" , " {x: 1}" , " {a: 1, $sortKey: {$meta: 'sortKey'}}" , " an~ax|_id-a" );
167+ testComputeKey (" {}" , " {}" , " {a: 1}" , " an|_id-a" );
150168
151169 // With or-elimination and projection
152- testComputeKey (" {$or: [{a: 1}]}" , " {}" , " {_id: 0, a: 1}" , " eqa|e_idia " );
153- testComputeKey (" {$or: [{a: 1}]}" , " {}" , " {'a.$': 1}" , " eqa|ia.$ " );
170+ testComputeKey (" {$or: [{a: 1}]}" , " {}" , " {_id: 0, a: 1}" , " eqa|a " );
171+ testComputeKey (" {$or: [{a: 1}]}" , " {}" , " {'a.$': 1}" , " eqa" );
154172}
155173
156174// Delimiters found in user field names or non-standard projection field values
157175// must be escaped.
158176TEST (CanonicalQueryEncoderTest, ComputeKeyEscaped) {
159177 // Field name in query.
160- testComputeKey (" {'a,[]~|<>': 1}" , " {}" , " {}" , " eqa\\ ,\\ [\\ ]\\ ~\\ |<>" );
178+ testComputeKey (" {'a,[]~|- <>': 1}" , " {}" , " {}" , " eqa\\ ,\\ [\\ ]\\ ~\\ |\\ - <>" );
161179
162180 // Field name in sort.
163- testComputeKey (" {}" , " {'a,[]~|<>': 1}" , " {}" , " an~aa\\ ,\\ [\\ ]\\ ~\\ |<>" );
181+ testComputeKey (" {}" , " {'a,[]~|- <>': 1}" , " {}" , " an~aa\\ ,\\ [\\ ]\\ ~\\ |\\ - <>" );
164182
165183 // Field name in projection.
166- testComputeKey (" {}" , " {}" , " {'a,[]~|<>': 1}" , " an|ia \\ ,\\ [\\ ]\\ ~\\ |<>" );
184+ testComputeKey (" {}" , " {}" , " {'a,[]~|- <>': 1}" , " an|_id-a \\ ,\\ [\\ ]\\ ~\\ |\\ - <>" );
167185
168186 // Value in projection.
169- testComputeKey (" {}" , " {}" , " {a: 'foo,[]~|<>'}" , " an|ia " );
187+ testComputeKey (" {}" , " {}" , " {a: 'foo,[]~|- <>'}" , " an|_id-a " );
170188}
171189
172190// Cache keys for $geoWithin queries with legacy and GeoJSON coordinates should
0 commit comments