summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/accumulator_js_reduce.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline/accumulator_js_reduce.cpp')
-rw-r--r--src/mongo/db/pipeline/accumulator_js_reduce.cpp82
1 files changed, 44 insertions, 38 deletions
diff --git a/src/mongo/db/pipeline/accumulator_js_reduce.cpp b/src/mongo/db/pipeline/accumulator_js_reduce.cpp
index 71075978d6d..78058d5913d 100644
--- a/src/mongo/db/pipeline/accumulator_js_reduce.cpp
+++ b/src/mongo/db/pipeline/accumulator_js_reduce.cpp
@@ -32,6 +32,7 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/db/pipeline/accumulator_js_reduce.h"
#include "mongo/db/pipeline/make_js_function.h"
+#include "mongo/db/pipeline/map_reduce_options_gen.h"
namespace mongo {
@@ -120,47 +121,52 @@ Value AccumulatorInternalJsReduce::getValue(bool toBeMerged) {
if (_values.size() < 1) {
return Value{};
}
-
- const auto keySize = _key.getApproximateSize();
-
Value result;
- // Keep reducing until we have exactly one value.
- while (true) {
- BSONArrayBuilder bsonValues;
- size_t numLeft = _values.size();
- for (; numLeft > 0; numLeft--) {
- Value val = _values[numLeft - 1];
-
- // Do not insert if doing so would exceed the the maximum allowed BSONObj size.
- if (bsonValues.len() + keySize + val.getApproximateSize() > BSONObjMaxUserSize) {
- // If we have reached the threshold for maximum allowed BSONObj size and only have a
- // single value then no progress will be made on reduce. We must fail when this
- // scenario is encountered.
- size_t numNextReduce = _values.size() - numLeft;
- uassert(31392, "Value too large to reduce", numNextReduce > 1);
- break;
+ if (mrSingleReduceOptimizationEnabled && _values.size() == 1) {
+ // This optimization existed in the old Pre-4.4 MapReduce implementation. If the flag is
+ // set, then we should replicate the optimization. See SERVER-68766 for more details.
+ result = std::move(_values[0]);
+ } else {
+ const auto keySize = _key.getApproximateSize();
+
+ // Keep reducing until we have exactly one value.
+ while (true) {
+ BSONArrayBuilder bsonValues;
+ size_t numLeft = _values.size();
+ for (; numLeft > 0; numLeft--) {
+ Value val = _values[numLeft - 1];
+
+ // Do not insert if doing so would exceed the the maximum allowed BSONObj size.
+ if (bsonValues.len() + keySize + val.getApproximateSize() > BSONObjMaxUserSize) {
+ // If we have reached the threshold for maximum allowed BSONObj size and only
+ // have a single value then no progress will be made on reduce. We must fail
+ // when this scenario is encountered.
+ size_t numNextReduce = _values.size() - numLeft;
+ uassert(31392, "Value too large to reduce", numNextReduce > 1);
+ break;
+ }
+ bsonValues << val;
}
- bsonValues << val;
- }
- auto expCtx = getExpressionContext();
- auto reduceFunc = makeJsFunc(expCtx, _funcSource);
-
- // Function signature: reduce(key, values).
- BSONObj params = BSON_ARRAY(_key << bsonValues.arr());
- // For reduce, the key and values are both passed as 'params' so there's no need to set
- // 'this'.
- BSONObj thisObj;
- Value reduceResult =
- expCtx->getJsExecWithScope()->callFunction(reduceFunc, params, thisObj);
- if (numLeft == 0) {
- result = reduceResult;
- break;
- } else {
- // Remove all values which have been reduced.
- _values.resize(numLeft);
- // Include most recent result in the set of values to be reduced.
- _values.push_back(reduceResult);
+ auto expCtx = getExpressionContext();
+ auto reduceFunc = makeJsFunc(expCtx, _funcSource);
+
+ // Function signature: reduce(key, values).
+ BSONObj params = BSON_ARRAY(_key << bsonValues.arr());
+ // For reduce, the key and values are both passed as 'params' so there's no need to set
+ // 'this'.
+ BSONObj thisObj;
+ Value reduceResult =
+ expCtx->getJsExecWithScope()->callFunction(reduceFunc, params, thisObj);
+ if (numLeft == 0) {
+ result = reduceResult;
+ break;
+ } else {
+ // Remove all values which have been reduced.
+ _values.resize(numLeft);
+ // Include most recent result in the set of values to be reduced.
+ _values.push_back(reduceResult);
+ }
}
}