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
106
107
108
109
110
111
112
113
|
(function() {
"use strict";
load("jstests/libs/optimizer_utils.js"); // For checkCascadesOptimizerEnabled.
if (!checkCascadesOptimizerEnabled(db)) {
jsTestLog("Skipping test because the optimizer is not enabled");
return;
}
load("jstests/aggregation/extras/utils.js");
const collA = db.collA;
collA.drop();
const collB = db.collB;
collB.drop();
assert.commandWorked(collA.insert({a: 1, b: 1}));
assert.commandWorked(collA.insert({a: 2, b: 2}));
assert.commandWorked(collA.insert({a: 2, b: 3}));
assert.commandWorked(collA.insert({a: 3, b: 4}));
assert.commandWorked(collA.insert({a: 5, b: 5}));
assert.commandWorked(collA.insert({a: 6, b: 6}));
assert.commandWorked(collA.insert({a: 6, b: 7}));
assert.commandWorked(collB.insert({a: 2, b: 1}));
assert.commandWorked(collB.insert({a: 3, b: 2}));
assert.commandWorked(collB.insert({a: 3, b: 3}));
assert.commandWorked(collB.insert({a: 5, b: 4}));
assert.commandWorked(collB.insert({a: 6, b: 5}));
assert.commandWorked(collB.insert({a: 6, b: 6}));
assert.commandWorked(collB.insert({a: 7, b: 7}));
{
// Assert plan with nested fields. The top-level fields should be covered by the scans.
const res = collA.explain("executionStats").aggregate([
{$lookup: {from: "collB", localField: "a.a1", foreignField: "b.b1", as: "out"}}
]);
const binaryJoinNode = res.queryPlanner.winningPlan.optimizerPlan.child.child.child;
assert.eq("BinaryJoin", binaryJoinNode.nodeType);
const leftScan = binaryJoinNode.leftChild.child;
assert.eq("PhysicalScan", leftScan.nodeType);
assert(leftScan.fieldProjectionMap.hasOwnProperty("_id"));
assert(leftScan.fieldProjectionMap.hasOwnProperty("a"));
const rightScan = binaryJoinNode.rightChild;
assert.eq("PhysicalScan", rightScan.nodeType);
assert(rightScan.fieldProjectionMap.hasOwnProperty("b"));
}
try {
// TODO: these results need to be updated as the lookup implementation is completed. See
// comments visitor of DocumentSourceLookUp in abt/document_source_visitor.
// Prevent unwind and sort from being reordered with lookup.
assert.commandWorked(
db.adminCommand({'configureFailPoint': 'disablePipelineOptimization', 'mode': 'alwaysOn'}));
{
const res =
collA
.aggregate([
{$lookup: {from: "collB", localField: "a", foreignField: "a", as: "result"}},
{$unwind: '$result'},
{$project: {_id: 0, a: 1, b: 1, ra: '$result.a', rb: '$result.b'}},
{$project: {'result': 0}},
{$sort: {a: 1, b: 1, ra: 1, rb: 1}}
])
.toArray();
assert.eq(res, [
{a: 2, b: 2, ra: 2, rb: 1},
{a: 2, b: 3, ra: 2, rb: 1},
{a: 3, b: 4, ra: 3, rb: 2},
{a: 3, b: 4, ra: 3, rb: 3},
{a: 5, b: 5, ra: 5, rb: 4},
{a: 6, b: 6, ra: 6, rb: 5},
{a: 6, b: 6, ra: 6, rb: 6},
{a: 6, b: 7, ra: 6, rb: 5},
{a: 6, b: 7, ra: 6, rb: 6}
]);
}
collA.drop();
collB.drop();
assert.commandWorked(collA.insert({a: [1, 2], b: 1}));
assert.commandWorked(collB.insert({a: [2, 3], b: 1}));
assert.commandWorked(collB.insert({a: [1, 3], b: 1}));
{
const res =
collA
.aggregate([
{$lookup: {from: "collB", localField: "a", foreignField: "a", as: "result"}},
{$unwind: '$result'},
{$project: {_id: 0, a: 1, b: 1, ra: '$result.a', rb: '$result.b'}},
{$project: {'result': 0}},
{$sort: {a: 1, b: 1, ra: 1, rb: 1}}
])
.toArray();
assert.eq(res,
[{a: [1, 2], b: 1, ra: [1, 3], rb: 1}, {a: [1, 2], b: 1, ra: [2, 3], rb: 1}]);
}
} finally {
assert.commandWorked(
db.adminCommand({'configureFailPoint': 'disablePipelineOptimization', 'mode': 'off'}));
}
}());
|