summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Zolnierz <nicholas.zolnierz@mongodb.com>2022-08-30 19:43:42 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-09-06 13:46:21 +0000
commite187062b23c92bda0eef094ec222f555db783563 (patch)
tree14dd720f2b7a40b3c519b1d580a940e8c43f191f
parent2ddd8f10442cfd4f36edb258e854bbbfb0ede9bd (diff)
downloadmongo-e187062b23c92bda0eef094ec222f555db783563.tar.gz
SERVER-68691 Report variable references for $graphLookup 'restrictSearchWithMatch' filter
(cherry picked from commit 5521f98c392f8af2fbb678f3cbf8089b641d9dba)
-rw-r--r--jstests/aggregation/sources/graphLookup/filter.js89
-rw-r--r--src/mongo/db/pipeline/document_source_graph_lookup.h4
2 files changed, 61 insertions, 32 deletions
diff --git a/jstests/aggregation/sources/graphLookup/filter.js b/jstests/aggregation/sources/graphLookup/filter.js
index da828cb66c7..7cfbbef1682 100644
--- a/jstests/aggregation/sources/graphLookup/filter.js
+++ b/jstests/aggregation/sources/graphLookup/filter.js
@@ -8,32 +8,32 @@
(function() {
"use strict";
-var local = db.local;
-var foreign = db.foreign;
+let local = db.local;
+let foreign = db.foreign;
local.drop();
foreign.drop();
-var bulk = foreign.initializeUnorderedBulkOp();
-for (var i = 0; i < 100; i++) {
+let bulk = foreign.initializeUnorderedBulkOp();
+for (let i = 0; i < 100; i++) {
bulk.insert({_id: i, neighbors: [i - 1, i + 1]});
}
-assert.writeOK(bulk.execute());
-assert.writeOK(local.insert({starting: 0}));
+assert.commandWorked(bulk.execute());
+assert.commandWorked(local.insert([{starting: 0, foo: 1}, {starting: 1, foo: 2}]));
// Assert that the graphLookup only retrieves ten documents, with _id from 0 to 9.
-var res = local
- .aggregate({
- $graphLookup: {
- from: "foreign",
- startWith: "$starting",
- connectFromField: "neighbors",
- connectToField: "_id",
- as: "integers",
- restrictSearchWithMatch: {_id: {$lt: 10}}
- }
- })
- .toArray()[0];
+let res = local
+ .aggregate({
+ $graphLookup: {
+ from: "foreign",
+ startWith: "$starting",
+ connectFromField: "neighbors",
+ connectToField: "_id",
+ as: "integers",
+ restrictSearchWithMatch: {_id: {$lt: 10}}
+ }
+ })
+ .toArray()[0];
assert.eq(res.integers.length, 10);
@@ -62,7 +62,7 @@ assert.writeOK(foreign.insert({from: 2, to: 3, shouldBeIncluded: true}));
// Assert that the $graphLookup stops exploring when it finds a document that doesn't match the
// filter.
res = local
- .aggregate({
+ .aggregate([{
$graphLookup: {
from: "foreign",
startWith: "$starting",
@@ -71,14 +71,14 @@ res = local
as: "results",
restrictSearchWithMatch: {shouldBeIncluded: true}
}
- })
- .toArray()[0];
+ }, {$match: {starting: 0}}])
+ .toArray();
-assert.eq(res.results.length, 1);
+assert.eq(res[0].results.length, 1, tojson(res));
// $expr is allowed inside the 'restrictSearchWithMatch' match expression.
res = local
- .aggregate({
+ .aggregate([{
$graphLookup: {
from: "foreign",
startWith: "$starting",
@@ -87,14 +87,14 @@ res = local
as: "results",
restrictSearchWithMatch: {$expr: {$eq: ["$shouldBeIncluded", true]}}
}
- })
- .toArray()[0];
+ }, {$match: {starting: 0}}])
+ .toArray();
-assert.eq(res.results.length, 1);
+assert.eq(res[0].results.length, 1, tojson(res));
// $expr within `restrictSearchWithMatch` has access to variables declared at a higher level.
res = local
- .aggregate([{
+ .aggregate([{$sort: {starting: 1}}, {
$lookup: {
from: "local",
let : {foo: true},
@@ -108,11 +108,36 @@ res = local
restrictSearchWithMatch:
{$expr: {$eq: ["$shouldBeIncluded", "$$foo"]}}
}
- }],
+ }, {$sort: {starting: 1}}],
as: "array"
}
- }])
- .toArray()[0];
-
-assert.eq(res.array[0].results.length, 1);
+ }, {$match: {starting: 0}}])
+ .toArray();
+
+assert.eq(res[0].array[0].results.length, 1, tojson(res));
+
+// $graphLookup which references a let variable defined by $lookup should be treated as correlated.
+res = local.aggregate([{
+ $lookup: {
+ from: "local",
+ let : {foo: "$foo"},
+ pipeline: [{
+ $graphLookup: {
+ from: "foreign",
+ startWith: "$starting",
+ connectFromField: "to",
+ connectToField: "from",
+ as: "results",
+ restrictSearchWithMatch:
+ {$expr: {$eq: ["$from", "$$foo"]}}
+ }
+ }],
+ as: "array"
+ }
+}, {$sort: {starting: 1}}]).toArray();
+assert.eq(2, res.length);
+assert.eq(1, res[1].starting, tojson(res));
+assert.eq(2, res[1].array.length, tojson(res));
+assert.eq(0, res[1].array[0].results.length, tojson(res));
+assert.eq(0, res[1].array[1].results.length, tojson(res));
})();
diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.h b/src/mongo/db/pipeline/document_source_graph_lookup.h
index e32f68b014a..129164ab45b 100644
--- a/src/mongo/db/pipeline/document_source_graph_lookup.h
+++ b/src/mongo/db/pipeline/document_source_graph_lookup.h
@@ -107,6 +107,10 @@ public:
DepsTracker::State getDependencies(DepsTracker* deps) const final {
_startWith->addDependencies(deps);
+ if (_additionalFilter) {
+ uassertStatusOK(MatchExpressionParser::parse(*_additionalFilter, _fromExpCtx))
+ ->addDependencies(deps);
+ }
return DepsTracker::State::SEE_NEXT;
};