1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
/**
* Test $match with $in is supported and returns correct results.
*/
load('jstests/aggregation/extras/utils.js'); // For assertArrayEq.
(function() {
"use strict";
const coll = db.cqf_match_with_in;
coll.drop();
const docs = [
{_id: 0},
{_id: 1, a: null},
{_id: 2, a: 1, b: {c: 1}},
{_id: 3, a: 2, b: {c: 2}},
{_id: 4, a: [], b: {c: 3}},
{_id: 5, a: [1]},
{_id: 6, a: ['1']},
{_id: 7, a: [[1]]},
{_id: 8, a: {}},
{_id: 9, a: {c: 1}},
{_id: 10, a: [{c: 1}]},
{_id: 11, a: [[{c: 1}]]},
{_id: 12, a: [[[1]]]},
];
assert.commandWorked(coll.insert(docs));
const runTest = (filter, expected) => {
try {
// Disabled in order to exercise $in translation directly.
assert.commandWorked(db.adminCommand(
{'configureFailPoint': 'disablePipelineOptimization', 'mode': 'alwaysOn'}));
const result = coll.aggregate({$match: filter}).toArray();
assertArrayEq(
{actual: result, expected: expected, extraErrorMsg: tojson({filter: filter})});
} finally {
assert.commandWorked(
db.adminCommand({'configureFailPoint': 'disablePipelineOptimization', 'mode': 'off'}));
}
};
const tests = [
// Test comparison to null.
{filter: {a: {$in: [null]}}, expected: [docs[0], docs[1]]},
// Test empty in-list.
{filter: {a: {$in: []}}, expected: []},
// Test traversal and type bracketing behavior.
{filter: {a: {$in: [1]}}, expected: [docs[2], docs[5]]},
{filter: {a: {$in: ['1']}}, expected: [docs[6]]},
{filter: {a: {$in: [1, '1']}}, expected: [docs[2], docs[5], docs[6]]},
{filter: {a: {$in: [1, 2]}}, expected: [docs[2], docs[3], docs[5]]},
{filter: {a: {$in: [1, 2, {}]}}, expected: [docs[2], docs[3], docs[5], docs[8]]},
// Test $in with $elemMatch.
{filter: {a: {$elemMatch: {$in: [1, 2]}}}, expected: [docs[5]]},
{filter: {a: {$elemMatch: {$in: [[1]]}}}, expected: [docs[7]]},
{filter: {a: {$elemMatch: {$in: [[[1]]]}}}, expected: [docs[12]]},
// Test comparisons to arrays.
{filter: {a: {$in: [[]]}}, expected: [docs[4]]},
{filter: {a: {$in: [[1]]}}, expected: [docs[5], docs[7]]},
{filter: {a: {$in: [[[1]]]}}, expected: [docs[7], docs[12]]},
// Test comparison to objects.
{filter: {a: {$in: [{}, {c: 1}]}}, expected: [docs[8], docs[9], docs[10]]},
// Test compound predicates.
{filter: {a: {$in: [1, 2]}, 'b.c': {$in: [2, 3]}}, expected: [docs[3]]},
{filter: {a: {$in: [1, 2]}, 'b.c': {$in: []}}, expected: []},
{filter: {a: {$in: [1, 2]}, 'b.c': {$in: [null]}}, expected: [docs[5]]},
// Test $type.
{
filter: {a: {$type: "array"}},
expected: [docs[4], docs[5], docs[6], docs[7], docs[10], docs[11], docs[12]]
},
{filter: {a: {$type: "double"}}, expected: [docs[2], docs[3], docs[5]]},
{filter: {a: {$type: "object"}}, expected: [docs[8], docs[9], docs[10]]},
];
for (const testData of tests) {
runTest(testData.filter, testData.expected);
}
}());
|