Reputation: 19000
I have a MongoDB collection with a document structure similar to:
{
"_id" : "xxx",
"inner : {
"foo" : 1,
"bar" : 2
}
}
Database version is 4.2.6
and an aggregation pipeline whose penultimate stage is $project
with an outcome document matching something like this one:
{
"_id" : "xxx",
"inner : {
"baz" : 3
}
}
Followed by a final stage to merge into the collection:
{
"$merge" : {
into: "myCollection",
on: "_id",
whenMatched: "merge",
whenNotMatched: "discard"
}
}
However as a result, the existing inner
document fields are overridden by the $merge
results. Meaning:
Expected results:
{
"_id" : "xxx",
"inner : {
"foo" : 1,
"bar" : 2,
"baz" : 3
}
}
Actual results:
{
"_id" : "xxx",
"inner : {
"baz" : 3
}
}
How can I overcome this?
Upvotes: 1
Views: 4548
Reputation: 19000
The accepted answer was a good lead, although the $project
pipeline caused every field except for _id
and inner
to be overridden. This is not what I had wanted of course.
What should have been the obvious choice, was simply to use $addFields
instead:
whenMatched: [
{"$addFields" :
{"inner.baz": "$$new.baz"}
}
]
Upvotes: 4
Reputation: 8693
The "merge" option merges the root document, so inner
field is replaced in your query.
Try to replace the merge with this merge that uses pipeline.
I haven't tested it but i think it will be ok.
$$new
variable is mongo-defined to refer to the document coming from pipeline.
{
"$merge" : {
into: "myCollection",
on: "_id",
whenMatched:
[{"$project":
{"_id": "$_id",
"inner": {"$mergeObjects": ["$inner","$$new.inner"]}}}],
whenNotMatched: "discard"
}
}
Upvotes: 4