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()
);
I figured it out, it was my lack of general mongodb knowledge. I was not being specific enough and here is the working solution: