diff options
author | Ruslan Abdulkhalikov <ruslan.abdulkhalikov@mongodb.com> | 2021-06-25 13:29:12 -0700 |
---|---|---|
committer | Ruslan Abdulkhalikov <ruslan.abdulkhalikov@mongodb.com> | 2021-06-28 14:06:07 -0700 |
commit | 751eb739c00c463b54823e7ab6da74c40172365f (patch) | |
tree | ec102f5c88b3ebc1e288e465c1ba3fd14ba5f86d | |
parent | 903728cba6ef183f1ecf205b5ae9668aee42e630 (diff) | |
download | mongo-751eb739c00c463b54823e7ab6da74c40172365f.tar.gz |
SERVER-57914 make getField return missing values
(cherry picked from commit d3d1f3bfe78f39df042bed6bb31b80dbe0b479f8)
-rw-r--r-- | jstests/aggregation/expressions/expression_get_field.js | 9 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.h | 4 |
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, |