Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

mongodb - 'upsert' in an embedded document

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...