Welcome to OGeek Q&A 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 Reply

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...