【问题标题】:'upsert' in an embedded document嵌入文档中的“更新插入”
【发布时间】:2012-04-23 08:28:32
【问题描述】:

我目前有以下数据集:

{  
    '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
);

由于 component_id 上存在唯一索引,这将引发抱怨重复键的异常。

有没有办法自动添加具有不同语言环境的新“文档”并在它已经存在时更新它?根据使用位置运算符的文档将不适用于“更新插入”。

【问题讨论】:

    标签: mongodb


    【解决方案1】:

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

    为了做你想做的事,你需要将你的数据结构更改为:

    {
        "_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.nl_NL.url、_locales.en_US.url 等。目前我通过获取所有 _locales 数据并修改/添加我正在工作的语言环境来解决这个问题用“手动”。完成后,我将当前的“_locales”替换为新的。目前这已经足够了,但从性能角度来看,这可能不是一个好主意。
    • 我同意,由于索引的原因,拥有“未定义”键通常不是一件好事。有时,如果在其他情况下由于索引/其他原因而提高了性能,那么最好执行两个查询来进行更新。大多数时候没有真正的“正确方法”。使用它,如果它不执行,则将其更改回来并运行两个查询以进行更新。
    • @Derick:我面临着类似的问题。 stackoverflow.com/questions/32038606/…
    猜你喜欢
    • 2018-09-04
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多