summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/document_source_graph_lookup.cpp
diff options
context:
space:
mode:
authorTed Tuckman <ted.tuckman@mongodb.com>2021-10-21 12:52:03 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-21 13:15:57 +0000
commit4f5e64a4f2fbac9b12a24b26dddb6b772fd21e37 (patch)
treea885fdd0284c705bf449ea8bcfe4aef26b7d8d2a /src/mongo/db/pipeline/document_source_graph_lookup.cpp
parent19cf54eb17cf933dfabf5a553660d93319e51713 (diff)
downloadmongo-4f5e64a4f2fbac9b12a24b26dddb6b772fd21e37.tar.gz
SERVER-60755 Distinguish between null, missing, and undefined in $graphLookup
Diffstat (limited to 'src/mongo/db/pipeline/document_source_graph_lookup.cpp')
-rw-r--r--src/mongo/db/pipeline/document_source_graph_lookup.cpp27
1 files changed, 27 insertions, 0 deletions
diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.cpp b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
index df0dbe22e13..60e74b9c043 100644
--- a/src/mongo/db/pipeline/document_source_graph_lookup.cpp
+++ b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
@@ -401,6 +401,11 @@ boost::optional<BSONObj> DocumentSourceGraphLookUp::makeMatchStageFromFrontier(
//
// We wrap the query in a $match so that it can be parsed into a DocumentSourceMatch when
// constructing a pipeline to execute.
+
+ // $match stages will conflate null, and undefined values. Keep track of which ones are
+ // present and eliminate documents that would match the others later.
+ bool matchNull = false;
+ bool matchUndefined = false;
BSONObjBuilder match;
{
BSONObjBuilder query(match.subobjStart("$match"));
@@ -417,11 +422,33 @@ boost::optional<BSONObj> DocumentSourceGraphLookUp::makeMatchStageFromFrontier(
{
BSONArrayBuilder in(subObj.subarrayStart("$in"));
for (auto&& value : _frontier) {
+ if (value.getType() == BSONType::jstNULL) {
+ matchNull = true;
+ } else if (value.getType() == BSONType::Undefined) {
+ matchUndefined = true;
+ }
in << value;
}
}
}
}
+ // We never want to see documents where the 'connectToField' is missing.
+ auto existsMatch = BSON(_connectToField.fullPath() << BSON("$exists" << true));
+ andObj << existsMatch;
+ // If matching null or undefined, make sure we don't match the other one.
+ if (matchNull || matchUndefined) {
+ if (!matchUndefined) {
+ auto notUndefined =
+ BSON(_connectToField.fullPath() << BSON("$not" << BSON("$type"
+ << "undefined")));
+ andObj << notUndefined;
+ } else if (!matchNull) {
+ auto notUndefined =
+ BSON(_connectToField.fullPath() << BSON("$not" << BSON("$type"
+ << "null")));
+ andObj << notUndefined;
+ }
+ }
}
}