From fe13637b2bf0ed26970d1103c6e9254c0887c48a Mon Sep 17 00:00:00 2001 From: Steve Tarzia Date: Mon, 7 Mar 2022 23:01:01 +0000 Subject: SERVER-62242 fixed $indexOfArray handling of duplicate vals in const arrays --- jstests/aggregation/bugs/server62242.js | 32 ++++++++++++++++++++++++++++++++ src/mongo/db/pipeline/expression.cpp | 6 +++--- 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 jstests/aggregation/bugs/server62242.js diff --git a/jstests/aggregation/bugs/server62242.js b/jstests/aggregation/bugs/server62242.js new file mode 100644 index 00000000000..273dddbf16d --- /dev/null +++ b/jstests/aggregation/bugs/server62242.js @@ -0,0 +1,32 @@ +// SERVER-62242 +// $indexOfArray does not work with duplicate values in array +(function() { +"use strict"; + +const c = db[jsTest.name()]; +c.drop(); + +c.save({_id: 0, number: 222}); + +// before SERVER-62242, this incorrectly returned {_id: 0, number: 222, idx: -1} +assert.eq( + [{_id: 0, number: 222, idx: 2}], + c.aggregate([{$addFields: {idx: {$indexOfArray: [[111, 111, 222], "$number"]}}}]).toArray()); + +// this query was OK +assert.eq([{_id: 0, number: 222, idx: 2}], + c.aggregate([ + {$addFields: {idx: {$indexOfArray: [[111, 111, 222, 333], "$number"]}}} + ]).toArray()); + +// also test for cases where a range is specified +assert.eq([{_id: 0, number: 222, idx: -1}], + c.aggregate([ + {$addFields: {idx: {$indexOfArray: [[111, 111, 222, 333], "$number", 0, 1]}}} + ]).toArray()); + +assert.eq([{_id: 0, number: 222, idx: 3}], + c.aggregate([ + {$addFields: {idx: {$indexOfArray: [[111, 111, 222, 222, 333], "$number", 3, 5]}}} + ]).toArray()); +})(); diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index a1b99d4d307..0fce881ba18 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -3443,14 +3443,14 @@ public: } virtual Value evaluate(const Document& root, Variables* variables) const { - - auto args = evaluateAndValidateArguments(root, _children, _indexMap.size(), variables); + int arraySize = _children[0]->evaluate(root, variables).getArrayLength(); + auto args = evaluateAndValidateArguments(root, _children, arraySize, variables); auto indexVec = _indexMap.find(args.targetOfSearch); if (indexVec == _indexMap.end()) return Value(-1); - // Search through the vector of indecies for first index in our range. + // Search through the vector of indexes for first index in our range. for (auto index : indexVec->second) { if (index >= args.startIndex && index < args.endIndex) { return Value(index); -- cgit v1.2.1