'Mongocxx - Update an array within a document?
I have a document in MongoDB with the following structure:
{
"_id":"$oid":"621fbaeaeedd1c000e60fbd2"},
"username":"myuser",
"password":"mypassword",
"comments":["comment1", "comment2", "comment3"]
}
I have a vector of comments:
std::vector<std::string> mycomments;
mycomments.push_back("comment2");
mycomments.push_back("comment4");
I would like to insert, if it is not already present, each string of the vector "mycomments" into the array "comments" in MongoDB document. I read MongoDB documentation, but I did not understand how to use the function "update_one", as in the documentation there is only a very simple case. So the solution that I adopted is the following: I get the content of comments and I put it into a vector, I push each string of mycomments into this vector (if it is not already present), then I delete the document in MongoDB and I insert a new document with new values:
bsoncxx::stdx::optional<bsoncxx::document::value> res = collection.find_one(document{} << "username" << username << finalize);
if (res)
{
coll.delete_one(document{} << "username" << username << finalize);
document data_builder{};
data_builder << "username" << username << "password" << password;
auto array_builder = data_builder << "comments" << open_array;
for (std::string str : myNewVector)
{
array_builder << str;
}
array_builder << close_array;
bsoncxx::document::view_or_value doc = data_builder << finalize;
coll.insert_one(doc);
}
Clearly this is a very foolish solution, since it would be enough to use the update_one function, but from the documentation I cannot understand how to use it (in this complex case). Can you help me please?
Solution 1:[1]
One way to add multiple strings to an array without duplicates is with the $addToSet operator and the $each modifier:
coll.update_one(
make_document( kvp("username", "myuser") ), // filter part
make_document( // update part
kvp("$addToSet",
make_document( kvp("comments",
make_document( kvp("$each",
make_array("comment2", "comment4")))))))
);
Solution 2:[2]
If you want to keep the order, then you must get the document and only push the comments that are not already present in it.
Then, you can use the $push and $each modifier.
Here's the reference: https://docs.mongodb.com/manual/reference/operator/update/push/#append-multiple-values-to-an-array
I ran this code:
std::vector<std::string> mycomments;
mycomments.push_back("comment2");
mycomments.push_back("comment4");
auto eachDoc = document{};
auto arrayDoc = eachDoc << "$each" << open_array;
for (auto& comment : mycomments)
arrayDoc << comment;
arrayDoc << close_array;
auto findDoc = document{} << "username" << "myuser" << finalize;
auto update = document{} << "$push" << open_document << "comments" << eachDoc << close_document << finalize;
collection.update_one(findDoc.view(), update.view());
And I obtained: ["comment1", "comment2", "comment3", "comment2", "comment4"]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | SPM |
| Solution 2 |
