Mongodb editing specific fields within a subdocument

123 Views Asked by At

Using update_one() with $set allows me to update specific fields or add new fields to a document. Other fields in the document are not affected.

When working with subdocuments, update_one() and $set behavior is not consistent. For example, here I attempt to update a subdocument the same way, but existing fields within the subdocument are all replaced. Any existing subfields not referenced in the update_one() command will be removed. For example:

{
"_id" : ObjectId("5fd6866b3866cb3a10000012"),
"firstName" : "jane",
"lastName" : "doe",
"calculatedFields" : {
    "field1" : "a",
    "field2" : "b",
    "field3" : "c"
}

}

Here, I attempt to edit 1 and add 3 new fields to the 'calculatedFields' subdocument:

document subfields;
subfields.append(
    kvp("field3", "x"),
    kvp("field4", "d"),
    kvp("field5", "e"),
    kvp("field6", "f")
);

doc.append(
    kvp("calculatedFields", subfields)
);

document update;
update.append(
    kvp("$set", doc)
);

auto result = collection.update_one(
    match.view(),
    update.view()
);

Here are the results, you can see that existing subfields have been removed:

{
    "_id" : ObjectId("5fd6866b3866cb3a10000012"),
    "firstName" : "jane",
    "lastName" : "doe",
    "calculatedFields" : {
        "field3" : "x",
        "field4" : "d",
        "field5" : "e",
        "field6" : "f",
    }
}

This is the result that I had expected from the update_one() operation:

{
    "_id" : ObjectId("5fd6866b3866cb3a10000012"),
    "firstName" : "jane",
    "lastName" : "doe",
    "calculatedFields" : {
        "field1" : "a",
        "field2" : "b",
        "field3" : "x",
        "field4" : "d",
        "field5" : "e",
        "field6" : "f",
    }
}

Here is a simplified way to look at what I am doing that does the exact same thing and leads to exactly the same results:

    document subfields;
    subfields.append(
        kvp("calculatedFields",
            make_document(
                kvp("field3", "x"),
                kvp("field4", "d"),
                kvp("field5", "e"),
                kvp("field6", "f")
            )
        )
    );

document update;
update.append(
    kvp("$set", subfields)
);

auto result = collection.update_one(
    match.view(),
    update.view()
);
1

There are 1 best solutions below

0
On

I figured it out, it was my lack of general mongodb knowledge. I was not being specific enough and here is the working solution:

document subfields;
subfields.append(
    kvp("calculatedFields.field3", "x"),
    kvp("calculatedFields.field4", "d"),
    kvp("calculatedFields.field5", "e"),
    kvp("calculatedFields.field6", "f")
);