1

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?

2 Answers 2

4

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"
    }
}
Sign up to request clarification or add additional context in comments.

Comments

4

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"}
     }
 ]

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.