编辑嵌套在数组元素mongo中的数组元素

时间:2016-08-31 10:40:26

标签: mongodb

我有一个基于mongo的应用程序,可以显示报告。 在每个报告中,用户可以发布向所有其他用户显示的评论,以及回复现有评论。有两个"级别"评论,最高评论没有"父母",并回复"父母"。评论存储在数组"讨论"中,每个都有另一个名为"回复"的数组。

db.reports.findOne()
{
    "_id" : "L154654258",
    "timestamp" : ISODate("2016-03-17T01:15:00Z"),
    "title" : "Server Offline",
    "content" : "A server has become offline due to reason X112",
    "discussions" : [
        {
            "id" : ObjectId("57beb8068d9da75ed44e0ebc"),
            "user_id" : "david",
            "timestamp" : ISODate("2016-03-17T01:15:00Z"),
            "comment" : "Is this the first time that it happens?",
            "last_edit" : null,
            "replies" : [
                {
                    "id" : ObjectId("57beb8068d9da75ed44e0ebd"),
                    "user_id" : "gene",
                    "timestamp" : ISODate("2016-03-17T01:20:00Z"),
                    "comment" : "I have never seen anything like that before",
                    "last_edit" : null
                },
                {
                    "id" : ObjectId("57c480b7ee568ddc634fd977"),
                    "user_id" : "david",
                    "timestamp" : ISODate("2016-03-20T01:20:00Z"),
                    "comment" : "Thanks!",
                    "last_edit" : null
                }
        }
    ]
}

到目前为止,使用此方案,我能够处理为每个评论插入新项目(父母和回复),以及编辑父母的内容(如果用户选择编辑他们的帖子),使用位置$运算符。 我的问题是更新回复。我试过这个(我以为它不会工作,只是想测试一下):

db.reports.findOne({'_id': 'L154654258', 'discussions': {'$elemMatch': {'id': ObjectId("57beb8068d9da75ed44e0ebc"), 'replies': {'$elemMatch': {'id': ObjectId("57beb8068d9da75ed44e0ebd")}}}}},
{'$set' : {'discussions.$.replies.$.comment': "This is a test!", 'discussions.$.replies.$.last_edit': 'Fantastic'}}
)

使用findOne()测试此查询似乎表明查询的查找部分有效。但是,如何更新数组的数组元素? 我假设使用$运算符两次没有工作,但有没有办法做到这一点,还是我需要使用Javascript? 谢谢!

4 个答案:

答案 0 :(得分:1)

您无法使用$运算符执行此操作。它将始终更新第一个元素。您必须找到该文档,在服务器中进行更改,然后将其保存回mongo。

答案 1 :(得分:1)

尝试以下内容: -

var findQuery = {'_id': 'L154654258', 'discussions.replies.id': ObjectId("57beb8068d9da75ed44e0ebd")};

db.restaurants.find(
findQuery).toArray(
function(err, result)
{
    if(err)
    {
         console.log(err);
    }
    else if(result && result.length)
    {
      var index,found = false;
     for(var j in result[0].discussions){
      for(var i in result[0].discussions[j].replies)
      {
         if(results[0].discussions[j].replies[i].id == ObjectId("57beb8068d9da75ed44e0ebd"))
         {
            found = true;
            index = i;
            break;
        }  
     }
   }

   if(found)
   {
        var x = 'discussions.$.replies.'+index+'.last_edit';

        var     updateObject = {$set : {}};    
        updateObject['$set'][x] = 'Fantastic';

        db.restaurants.update(findQuery, updateObject);
    }
  });
}

答案 2 :(得分:0)

根据Sharabanee的代码,以下代码对我有用:

var findQuery = {'_id': 'L154654258', 'discussions.replies.id': ObjectId("57beb8068d9da75ed44e0ebd")};
var result = db.reports.find(findQuery).toArray();
var index,found = false;
for(var j in result[0].discussions) {
    for(var i in result[0].discussions[j].replies) {
         if(result[0].discussions[j].replies[i].id.equals(ObjectId("57beb8068d9da75ed44e0ebd"))) {
            found = true;
            index = i;
            break;
        }  
    }
}
if(found) {
    var x = 'discussions.$.replies.'+index+'.comment';

    var  updateObject = {$set : {}};    
    updateObject['$set'][x] = 'Fantastic';

    db.reports.update(findQuery, updateObject);
}

答案 3 :(得分:0)

我知道这篇文章很旧,但是我只是在寻找自己如何更新Mongo中数组数组中的元素。

由于使用了update(从v3.6开始),因此可以使用arrayFilters在Mongo中进行纯粹的操作而不必知道数组中的位置。

还有另一个答案,详细说明了如何使用here中发现的答案。

我希望这可以帮助某人也寻求解决此问题的方法,而无需使用Mongo以外的代码引入竞争条件。