I currently have the following dataset:
{
'component_id':1,
'_locales':[
{
'url': 'dutch',
'locale': 'nl_NL'
}
] (etc)
}
If I want to update the row with the locale I would run something similar to:
db.components.update(
{'component_id': 1, '_locales.locale': 'nl_NL'},
{$set: {'_locales.$': {'url': 'new url','locale':'nl_NL'}},
true
);
This works fine untill the locale does not exists:
db.components.update(
{'component_id': 1, '_locales.locale': 'en_US'},
{$set: {'_locales.$': {'url': 'new url','locale':'en_US'}},
true
);
since there is a unique index on component_id this will throw an exception complaining about a duplicate key.
Is there a way to automatically add the new 'document' with a different locale and update it if it already exists? According to the documentation using the position operator will not work with 'upserting'.
Or in other words, upsert is a combination of update and insert (update + insert = upsert). If the value of this option is set to true and the document or documents found that match the specified query, then the update operation will update the matched document or documents.
Update Documents in an ArrayThe positional $ operator facilitates updates to arrays that contain embedded documents. Use the positional $ operator to access the fields in the embedded documents with the dot notation on the $ operator.
Here in MongoDB, the upsert option is a Boolean value. Suppose the value is true and the documents match the specified query filter. In that case, the applied update operation will update the documents. If the value is true and no documents match the condition, this option inserts a new document into the collection.
May 20, 2019. In MongoDB, an upsert means an update that inserts a new document if no document matches the filter . To upsert a document in Mongoose, you should set the upsert option to the Model. updateOne() function: const res = await Character.
You can use $addToSet to add to a set making sure there is no duplicate array element, but that will not work for your "updating" case.
In order to do what you want, you will need to change your data structure to something like:
{
"_id" : ObjectId("4f9519d6684c8b1c9e72e367"),
"component_id" : 1,
"_locales" : {
"nl_NL" : {
"url" : "dutch"
}
}
}
Now you can do an update on the nl_NL locale with just:
db.components.update( { component_id: 1 }, { $set: { '_locales.nl_NL.url' : 'new url' } }, true );
And a new locale will work as well, such as with:
db.components.update( { component_id: 1 }, { $set: { '_locales.en_US.url' : 'American' } }, true );
You might want to consider to having the locale as part of the nested object as well perhaps, like in:
{
"_id" : ObjectId("4f9519d6684c8b1c9e72e367"),
"component_id" : 1,
"_locales" : {
"nl_NL" : {
"url" : "dutch"
"locale" : "nl_NL"
}
}
}
This makes it easier to retrieve data in some cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With