diff options
author | Nicholas Zolnierz <nicholas.zolnierz@mongodb.com> | 2022-08-30 19:43:42 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-09-02 18:05:44 +0000 |
commit | 4b37709d13d1ee29cb0420f875af4cd19d3c2a6c (patch) | |
tree | 32ac27ec10f98c802509893012ccab188f00049c | |
parent | 2f624f66f3044e7066d86420b2b6151a19947064 (diff) | |
download | mongo-4b37709d13d1ee29cb0420f875af4cd19d3c2a6c.tar.gz |
SERVER-68691 Report variable references for $graphLookup 'restrictSearchWithMatch' filter
(cherry picked from commit 5521f98c392f8af2fbb678f3cbf8089b641d9dba)
-rw-r--r-- | jstests/aggregation/sources/graphLookup/filter.js | 87 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_graph_lookup.h | 4 |
2 files changed, 60 insertions, 31 deletions
diff --git a/jstests/aggregation/sources/graphLookup/filter.js b/jstests/aggregation/sources/graphLookup/filter.js index 5f815c08c93..3b786b94f14 100644 --- a/jstests/aggregation/sources/graphLookup/filter.js +++ b/jstests/aggregation/sources/graphLookup/filter.js @@ -10,32 +10,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.commandWorked(bulk.execute()); -assert.commandWorked(local.insert({starting: 0})); +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); @@ -64,7 +64,7 @@ assert.commandWorked(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", @@ -73,14 +73,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", @@ -89,14 +89,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}, @@ -110,11 +110,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 ee930e1a017..34813e42960 100644 --- a/src/mongo/db/pipeline/document_source_graph_lookup.h +++ b/src/mongo/db/pipeline/document_source_graph_lookup.h @@ -112,6 +112,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; }; |