summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuslan Abdulkhalikov <ruslan.abdulkhalikov@mongodb.com>2021-06-25 13:29:12 -0700
committerRuslan Abdulkhalikov <ruslan.abdulkhalikov@mongodb.com>2021-06-28 14:06:07 -0700
commit751eb739c00c463b54823e7ab6da74c40172365f (patch)
treeec102f5c88b3ebc1e288e465c1ba3fd14ba5f86d
parent903728cba6ef183f1ecf205b5ae9668aee42e630 (diff)
downloadmongo-751eb739c00c463b54823e7ab6da74c40172365f.tar.gz
SERVER-57914 make getField return missing values
(cherry picked from commit d3d1f3bfe78f39df042bed6bb31b80dbe0b479f8)
-rw-r--r--jstests/aggregation/expressions/expression_get_field.js9
-rw-r--r--src/mongo/db/pipeline/expression.cpp14
-rw-r--r--src/mongo/db/pipeline/expression.h4
3 files changed, 16 insertions, 11 deletions
diff --git a/jstests/aggregation/expressions/expression_get_field.js b/jstests/aggregation/expressions/expression_get_field.js
index 922bbad68ad..017ead1cee1 100644
--- a/jstests/aggregation/expressions/expression_get_field.js
+++ b/jstests/aggregation/expressions/expression_get_field.js
@@ -65,7 +65,6 @@ assertGetFieldFailedWithCode({field: "a"}, 3041703);
// Test that $getField fails with a document with one or more arguments of incorrect type.
assertGetFieldFailedWithCode({field: true, input: {a: "b"}}, 5654602);
assertGetFieldFailedWithCode({field: {"a": 1}, input: {"a": 1}}, 5654601);
-assertGetFieldFailedWithCode({field: "a", input: true}, 3041705);
assertGetFieldFailedWithCode(5, 5654602);
assertGetFieldFailedWithCode(true, 5654602);
assertGetFieldFailedWithCode({field: null, input: {"a": 1}}, 5654602);
@@ -120,6 +119,8 @@ assertGetFieldResultsEq({field: "a.b.c", input: {$const: {"a.b.c": 5}}},
[{_id: 0, test: 5}, {_id: 1, test: 5}]);
assertGetFieldResultsEq({field: "a.b.c", input: {a: {b: {c: 5}}}},
[{_id: 0}, {_id: 1}]); // The test field should evaluate to missing.
+assertGetFieldResultsEq({field: "d", input: {$getField: "c"}},
+ [{_id: 0, "test": "x"}, {_id: 1, "test": "x"}]);
// Test that $getField works with fields that contain '$'.
assertGetFieldResultsEq({field: "a$b", input: {"a$b": "b"}},
@@ -150,6 +151,10 @@ assertGetFieldResultsEq({field: "a", input: {}},
assertGetFieldResultsEq({$const: "$v.."}, [{_id: 0, test: null}, {_id: 1, test: null}]);
assertGetFieldResultsEq({$const: "$u.."},
[{_id: 0}, {_id: 1}]); // The test field should evaluate to missing.
+assertGetFieldResultsEq({field: "doesNotExist2", input: {$getField: "doesNotExist1"}},
+ [{_id: 0}, {_id: 1}]);
+assertGetFieldResultsEq({field: "x", input: {$getField: "doesNotExist"}}, [{_id: 0}, {_id: 1}]);
+assertGetFieldResultsEq({field: "a", input: true}, [{_id: 0}, {_id: 1}]);
// Test case where $getField stages are nested.
assertGetFieldResultsEq(
@@ -160,7 +165,7 @@ assertGetFieldResultsEq(
[{_id: 0}, {_id: 1}]);
assertGetFieldResultsEq(
{field: "a", input: {$getField: {field: "b.d", input: {$const: {"b.c": {a: 5}}}}}},
- [{_id: 0, test: null}, {_id: 1, test: null}]);
+ [{_id: 0}, {_id: 1}]);
assertGetFieldResultsEq({field: {$const: "$a"}, input: {$getField: {$const: "$x..$y"}}},
[{_id: 0, test: 1}, {_id: 1, test: 1}]);
assertGetFieldResultsEq({field: {$const: "$b..$c"}, input: {$getField: {$const: "$x..$y"}}},
diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp
index 268e5f052ac..664c3f81425 100644
--- a/src/mongo/db/pipeline/expression.cpp
+++ b/src/mongo/db/pipeline/expression.cpp
@@ -7314,15 +7314,15 @@ Value ExpressionGetField::evaluate(const Document& root, Variables* variables) c
auto inputValue = _input->evaluate(root, variables);
if (inputValue.nullish()) {
- return Value(BSONNULL);
+ if (inputValue.missing()) {
+ return Value();
+ } else {
+ return Value(BSONNULL);
+ }
+ } else if (inputValue.getType() != BSONType::Object) {
+ return Value();
}
- uassert(3041705,
- str::stream() << kExpressionName
- << " requires 'input' to evaluate to type Object, "
- "but got "
- << typeName(inputValue.getType()),
- inputValue.getType() == BSONType::Object);
return inputValue.getDocument().getField(fieldValue.getString());
}
diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h
index 0438e2d0eb1..64b7c053433 100644
--- a/src/mongo/db/pipeline/expression.h
+++ b/src/mongo/db/pipeline/expression.h
@@ -3512,8 +3512,8 @@ public:
* Constructs a $getField expression where 'field' is an expression resolving to a constant
* string Value and 'input' is an expression resolving to an object Value (or null).
*
- * If 'input' is nullish, $getField evaluates to null. Furthermore, if 'input' does not contain
- * 'field', then $getField returns missing.
+ * If 'input' is nullish (but not missing), $getField evaluates to null. Furthermore, if 'input'
+ * does not contain 'field', then $getField returns missing.
*/
ExpressionGetField(ExpressionContext* const expCtx,
boost::intrusive_ptr<Expression> field,