summaryrefslogtreecommitdiff
path: root/jstests/cqf/lookup.js
blob: 462dbd1821c82f2f252629e570f2a74aeda94455 (plain)
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'}));
}
}());