Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'upsert' in an embedded document

Tags:

mongodb

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'.

like image 993
Wim Wisselink Avatar asked Apr 23 '12 08:04

Wim Wisselink


People also ask

How does the Upsert option work?

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.

How do I update an embedded file in MongoDB?

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.

Is there an Upsert option in the MongoDB Insert command?

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.

What does Upsert mean mongoose?

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.


1 Answers

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.

like image 135
Derick Avatar answered Nov 16 '22 02:11

Derick