2

尝试在 Mongo 中更新子文档数组中的元素时遇到问题。如果我考虑集合“资源”中的以下文档

{
    "_id": 1,
    "resources": [
        {
            "resource_id": 1,
            "resource_list": ["item1","item2"]
        },
        {
            "resource_id": 2,
            "resource_list": ["item4","item3"]
        }
    ]
}

我想更新"item4"一些其他值,比如"item5"for"resource_id" = 2

以下语句给了我一个错误:如果没有包含数组的相应查询字段,则无法应用位置运算符

db.resource.update({"resources.resource_id": 2, "resources.resource_list": "item4"}, {$set: {"resources.$.resource_list.$": "item5"}})

对此的任何帮助将不胜感激。

4

2 回答 2

1

位置运算符只能在查询中使用一次。这是一个限制,有一个改进的开放票:https ://jira.mongodb.org/browse/SERVER-831

解决此问题的另一种方法是将“item5”推送到数组并拉取“item4”。像这样的东西:

db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $pull: { "resources.$.resource_list": "item4" }, $push: { "resources.$.resource_list": "item5" } })

但是,这也是不可能的,$pull并且$push不能在同一字段的同一查询中使用。相关票证:https ://jira.mongodb.org/browse/SERVER-1050

我看到两个解决方案。一是执行两个查询。在第一个查询中,您推送“item5”,在第二个查询中,您拉出“item4”:

db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $push: { "resources.$.resource_list": "item5" } });
db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $pull: { "resources.$.resource_list": "item4" } });

如果你想在一个查询中完成,你可以使用 mongo shell。像这样的东西:

db.resource.find({ 'resources.resource_id': 2, 'resources.resource_list': 'item4' }).forEach( function(document) {
  for (var i in document.resources) {
    if (document.resources[i].resource_id == 2) {
      var index = document.resources[i].resource_list.indexOf('item4');
      document.resources[i].resource_list[index] = 'item5';
      db.resource.save(document);
    }
  }
})
于 2014-03-30T22:59:44.307 回答
0

符号$仅修改搜索中最后一个数组的最后位置,您可以使用$addToSetor$push来添加项目...

 > db.resource.find()
    { "_id" : 1, 
      "resources" : [
                     { "resource_id" : 1,   
                       "resource_list" : [ "item1","item2" ] },     
                     { "resource_id" : 2, 
                       "resource_list" : [ "item4", "item3" ] } ] }

    > db.resource.update({"resources.resource_id": 2, 
                          "resources.resource_list": "item4"},
                         {$addToSet:{"resources.$.resource_list": "item5"}})

    > db.resource.find()
    { "_id" : 1, "resources" : [
                             { "resource_id" : 1, 
                               "resource_list" : [ "item1", "item2" ] },
                             { "resource_id" : 2, 
                               "resource_list" : [ "item4", "item3", "item5" ] } ] }

    > db.resource.update({"resources.resource_id": 2, 
                          "resources.resource_list": "item4"},
                         {$pull: {"resources.$.resource_list": "item4"}})

    > db.resource.find()
    { "_id" : 1, "resources" : [ 
                               { "resource_id" : 1,
                                 "resource_list" : [ "item1", "item2" ] },
                               { "resource_id" : 2,
                                 "resource_list" : [ "item3","item5" ] } ] }

但是同时运行两个查询更好吗?

> db.algo.update({"resources.resource_id": 2,
                  "resources.resource_list": "item4"}, 
                 {$addToSet:{"resources.$.resource_list": "item5"},
                   $pull: {"resources.$.resource_list": "item4"}})

修饰符不允许字段名称重复

于 2014-04-02T19:16:42.393 回答