“UPSERT”

问题描述:

目前,我有以下数据集:“UPSERT”

{ 
    '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上有一个唯一的索引,所以会抛出一个excep抱怨一个重复的密钥。

有没有办法自动添加新的“文档”与不同的语言环境,并更新它,如果它已经存在?根据使用位置运算符的文档不能用'插入'。

您可以使用$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); 

您可能要consid呃到具有语言环境嵌套对象的一部分,以及也许,像:

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

这使得它更容易找回在某些情况下的数据。

+1

嗨德里克,谢谢你的回复。你的建议实际上是我最初的数据结构,我改变了上述。一个原因是创建索引:_locales.url而不是在每个区域设置: _locales.nl_NL.url,_locales.en_US.url等 目前我通过获取所有_locales数据并修改/添加区域设置I '正在'手动'工作。当我完成后,我用新的替换当前的'_locales'。现在这样就足够了,表现明智这可能不是一个好主意。 – 2012-04-23 09:32:43

+0

我也同意,由于索引的原因,使用“未定义”键通常不是一件好事。有时,如果由于其他情况下的索引/其他原因而提高性能,则最好是执行两次查询来执行更新。大部分时间没有真正的“正确方式”。玩它,如果它不执行更改它并运行两个查询更新。 – Derick 2012-04-23 12:35:35

+0

@Derick:我正面临类似的问题。 http://*.com/questions/32038606/defining-a-map-with-objectid-key-and-array-of-strings-as-value-in-mongoose-schem – 2015-08-17 10:45:29