forked from mongodb/mongo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
match_with_and_or.js
105 lines (90 loc) · 3.16 KB
/
match_with_and_or.js
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**
* Test $match with $and/$or is supported and returns correct results.
*/
import {show} from "jstests/libs/golden_test.js";
import {resetCollection} from "jstests/query_golden/libs/utils.js";
const coll = db.and_or_coll;
const docs = [
// No 'a' path.
{x: 2},
// No 'a.b' path.
{a: 1, x: 2},
{a: {c: 1}},
{a: [1], x: 1},
{a: [1, 2, 3, "1"]},
// No 'a.b.c' path.
{a: {b: 1, x: 1}, x: 2},
{a: {b: [1, 2], x: 2}, x: 3},
{a: {b: [2, 3], x: 3}, x: 4},
{a: [{b: 1, x: 1}, {x: 2}], x: 3},
{a: [1, 2, {b: 1}, {b: 2}], x: 1},
{a: [{b: [1, 2], x: 1}, {x: 2}], x: 3},
{a: [{b: {d: [1, 2, 3]}, x: 1}, {x: 2}], x: 3},
// 'a.b.c' path exists.
{a: {b: {c: 1, x: 1}, x: 1}, x: 1},
{a: [1, 2, {b: [2, {c: 1}, {c: 2}, {x: 1}]}], x: 2},
{a: [1, 2, {b: 1}, {b: {c: 1}}, {b: {c: 2}}, {x: 1}, {x: {y: 1}}], x: 2},
{a: [{b: [{c: [1, 2]}]}]},
// There is a double array under 'a' which should not be traversed.
{a: [[1, {b: [1, 2, {c: 1}, {c: 2}]}]]},
];
const indexes = [
{a: 1},
{'a.b': 1},
{a: 1, x: 1},
];
resetCollection(coll, docs, indexes);
const andOrSpecs = [
// Where there is only one child.
[{a: 1}],
[{a: {$lt: 20}}],
[{a: {$lt: 20, $gt: 0}}],
// Where the predicates are over the same path.
[{a: 1}, {a: 2}],
[{a: 1}, {a: 1}],
[{a: {$in: [1, 3]}}, {a: {$in: [2, 4]}}],
[{'a.b': 1}, {'a.b': 2}],
[{a: {$lt: 20}}, {a: {$gt: 0}}],
[{a: {$gt: 0}}, {a: {$gte: 0}}],
[{a: {$lte: 1}}, {a: {$gte: 2}}],
[{a: {$lt: 20, $gt: 0}}, {a: {$lt: 10, $gt: -5}}],
[{a: {$gt: 1}}, {a: {$lt: "2"}}],
[{a: null}, {a: {$exists: false}}],
[{a: {$in: [1, 2, 3]}}, {a: {$in: [3, 4, 5]}}],
// Where the predicates form a contradiction.
[{a: 1}, {a: {$not: {$eq: 1}}}],
[{a: {$exists: false}}, {a: {$exists: true}}],
[{'a.b': {$exists: false}}, {'a.b': {$exists: true}}],
// Where the predicates are over paths with shared prefixes.
[{'a.b': 1}, {'a.x': 1}],
[{'a.b.c': 1}, {'a.x.y': 1}],
[{'a.b.c': 1}, {'a.b.x': 1}],
[{'a.b': 1}, {'a.b.c': 2}],
// Where some of the predicates are over completely disjoint paths.
[{a: 1}, {x: 2}],
[{a: 1}, {a: 2}, {'a.b': 1}, {x: 2}],
// Where one of the predicates is always-false or always-true.
[{_id: {$exists: true}}, {a: 1}],
[{/* should match everything */}, {a: 1}],
[{_id: {$exists: false}}, {a: 1}],
// Where the predicates are themselves ands/ors: 1 level of nesting.
[{$or: [{'a.b': 1}, {'a.b': 2}]}, {$and: [{x: {$exists: true}}, {a: {$exists: true}}]}],
// Where the predicates are themselves ands/ors: 2 levels of nesting.
[
{
$or: [
{$or: [{'a.b': 1}, {'a.b': 2}]},
{$and: [{x: {$exists: true}}, {'a.b.c': {$exists: true}}]}
]
},
{$and: [{$or: [{'a.b.c': 1}, {'a.b.c': 2}]}, {$and: [{a: 1}, {a: 2}]}]}
],
];
const operators = ["$and", "$or"];
for (const op of operators) {
for (const andOrSpec of andOrSpecs) {
const pipeline = [{$match: {[op]: andOrSpec}}];
jsTestLog(`Query: ${tojsononeline(pipeline)}`);
show(coll.aggregate(pipeline));
}
}