summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline')
-rw-r--r--src/mongo/db/pipeline/document_source_merge.cpp20
-rw-r--r--src/mongo/db/pipeline/document_source_merge.idl1
-rw-r--r--src/mongo/db/pipeline/document_source_merge_test.cpp10
3 files changed, 29 insertions, 2 deletions
diff --git a/src/mongo/db/pipeline/document_source_merge.cpp b/src/mongo/db/pipeline/document_source_merge.cpp
index 2d446b18166..dbe77e843f7 100644
--- a/src/mongo/db/pipeline/document_source_merge.cpp
+++ b/src/mongo/db/pipeline/document_source_merge.cpp
@@ -60,10 +60,11 @@ using WhenNotMatched = MergeStrategyDescriptor::WhenNotMatched;
using BatchTransform = std::function<void(DocumentSourceMerge::BatchedObjects&)>;
constexpr auto kStageName = DocumentSourceMerge::kStageName;
-constexpr auto kDefaultWhenMatched = WhenMatched::kReplaceWithNew;
+constexpr auto kDefaultWhenMatched = WhenMatched::kMerge;
constexpr auto kDefaultWhenNotMatched = WhenNotMatched::kInsert;
constexpr auto kReplaceWithNewInsertMode =
MergeMode{WhenMatched::kReplaceWithNew, WhenNotMatched::kInsert};
+constexpr auto kMergeInsertMode = MergeMode{WhenMatched::kMerge, WhenNotMatched::kInsert};
constexpr auto kFailInsertMode = MergeMode{WhenMatched::kFail, WhenNotMatched::kInsert};
/**
@@ -99,6 +100,19 @@ MergeStrategy makeInsertStrategy() {
}
/**
+ * Creates a batched objects transformation function which wraps each element of the 'batch.objects'
+ * array into the given 'updateOp' operator.
+ */
+BatchTransform makeUpdateTransform(const std::string& updateOp) {
+ return [updateOp](auto& batch) {
+ std::transform(batch.objects.begin(),
+ batch.objects.end(),
+ batch.objects.begin(),
+ [updateOp](const auto& obj) { return BSON(updateOp << obj); });
+ };
+}
+
+/**
* Returns a map that contains descriptors for all supported merge strategies for the $merge stage.
* Each descriptor is constant and stateless and thus, can be shared by all $merge stages. A
* descriptor is accessed using a pair of whenMatched/whenNotMatched merge modes, which defines the
@@ -118,6 +132,10 @@ const MergeStrategyDescriptorsMap& getDescriptors() {
{kReplaceWithNewInsertMode,
{ActionType::insert, ActionType::update},
makeUpdateStrategy(true, {})}},
+ {kMergeInsertMode,
+ {kMergeInsertMode,
+ {ActionType::insert, ActionType::update},
+ makeUpdateStrategy(true, makeUpdateTransform("$set"))}},
{kFailInsertMode, {kFailInsertMode, {ActionType::insert}, makeInsertStrategy()}}};
return mergeStrategyDescriptors;
}
diff --git a/src/mongo/db/pipeline/document_source_merge.idl b/src/mongo/db/pipeline/document_source_merge.idl
index 312d53ae56f..0ffaa2d877b 100644
--- a/src/mongo/db/pipeline/document_source_merge.idl
+++ b/src/mongo/db/pipeline/document_source_merge.idl
@@ -44,6 +44,7 @@ enums:
type: string
values:
kFail: "fail"
+ kMerge: "merge"
kReplaceWithNew: "replaceWithNew"
MergeWhenNotMatchedMode:
diff --git a/src/mongo/db/pipeline/document_source_merge_test.cpp b/src/mongo/db/pipeline/document_source_merge_test.cpp
index bb819de73cb..8970cc33a5b 100644
--- a/src/mongo/db/pipeline/document_source_merge_test.cpp
+++ b/src/mongo/db/pipeline/document_source_merge_test.cpp
@@ -47,7 +47,7 @@ constexpr StringData kWhenNotMatchedModeFieldName =
constexpr StringData kIntoFieldName = DocumentSourceMergeSpec::kTargetNssFieldName;
constexpr StringData kOnFieldName = DocumentSourceMergeSpec::kOnFieldName;
const StringData kDefaultWhenMatchedMode =
- MergeWhenMatchedMode_serializer(MergeWhenMatchedModeEnum::kReplaceWithNew);
+ MergeWhenMatchedMode_serializer(MergeWhenMatchedModeEnum::kMerge);
const StringData kDefaultWhenNotMatchedMode =
MergeWhenNotMatchedMode_serializer(MergeWhenNotMatchedModeEnum::kInsert);
@@ -602,6 +602,14 @@ TEST_F(DocumentSourceMergeTest, CorrectlyHandlesWhenMatchedAndWhenNotMatchedMode
<< "merge"
<< "whenNotMatched"
<< "insert"));
+ ASSERT(createMergeStage(spec));
+
+ spec = BSON("$merge" << BSON("into"
+ << "target_collection"
+ << "whenMatched"
+ << "keepExisting"
+ << "whenNotMatched"
+ << "insert"));
ASSERT_THROWS_CODE(createMergeStage(spec), DBException, ErrorCodes::BadValue);
spec = BSON("$merge" << BSON("into"