Mongodb ';向上插入';在嵌入的文档中

Mongodb ';向上插入';在嵌入的文档中,mongodb,Mongodb,我目前拥有以下数据集: { 'component_id':1, '_locales':[ { 'url': 'dutch', 'locale': 'nl_NL' } ] (etc) } 如果我想用区域设置更新行,我将运行类似于: db.components.update( {'component_id': 1, '_locales.locale': 'nl

我目前拥有以下数据集:

{  
    'component_id':1,  
    '_locales':[   
        {  
            'url': 'dutch',  
            'locale': 'nl_NL'  
        } 
    ] (etc)
}
如果我想用区域设置更新行,我将运行类似于:

db.components.update(
    {'component_id': 1, '_locales.locale': 'nl_NL'},
    {$set: {'_locales.$': {'url': 'new url','locale':'nl_NL'}}, 
    true
);
在区域设置不存在之前,此操作正常:

db.components.update(
    {'component_id': 1, '_locales.locale': 'en_US'},
    {$set: {'_locales.$': {'url': 'new url','locale':'en_US'}}, 
    true
);
由于组件_id上有一个唯一的索引,这将引发一个异常,抱怨密钥重复

是否有一种方法可以自动添加具有不同语言环境的新“文档”,并在其已存在时进行更新?根据文档,使用position运算符将无法使用“upserting”。

您可以使用添加到集合中,以确保没有重复的数组元素,但这对“更新”情况不起作用

为了实现您的目标,您需要将数据结构更改为:

{
    "_id" : ObjectId("4f9519d6684c8b1c9e72e367"),
    "component_id" : 1,
    "_locales" : {
        "nl_NL" : {
            "url" : "dutch"
        }
    }
}
现在,您只需使用以下工具即可对nl_nl语言环境进行更新:

db.components.update( { component_id: 1 }, { $set: { '_locales.nl_NL.url' : 'new url' } }, true );
新的区域设置也可以使用,例如:

db.components.update( { component_id: 1 }, { $set: { '_locales.en_US.url' : 'American' } }, true );

您可能想考虑将区域设置作为嵌套对象的一部分,也许类似于:

{
    "_id" : ObjectId("4f9519d6684c8b1c9e72e367"),
    "component_id" : 1,
    "_locales" : {
        "nl_NL" : {
            "url" : "dutch"
            "locale" : "nl_NL"                 
        }
    }
}

这使得在某些情况下检索数据更容易。

嗨,德里克,谢谢你的回复。您的建议实际上是我的初始数据结构,我将其更改为上述内容。一个原因是在:_locales.url上创建索引,而不是在每个locales上创建索引:_locales.nl_nl.url、_locales.en_US.url等。目前,我通过获取所有_locales数据并“手动”修改/添加正在使用的locale来解决这个问题。完成后,我将用新的替换当前的“\u locales”。就目前而言,就性能而言,这可能不是一个很好的主意。我同意,由于索引的原因,拥有一个“未定义”的键通常不是一件好事。有时,如果在其他情况下由于索引/其他原因而提高了性能,那么最好执行两个查询来进行更新。大多数时候,没有真正的“正确方法”。玩它,如果它不执行,请将其更改回并运行两个查询以进行更新。@Derick:我面临类似的问题。