8

我最近开始使用 MongoDB,我有一个关于更新文档中的数组的问题。我有这样的结构:

{
"_id" : ObjectId(),
"post" : "",
"comments" : [
        {
                "user" : "test",
                "avatar" : "/static/avatars/asd.jpg",
                "text" : "....."
        }
        {
                "user" : "test",
                "avatar" : "/static/avatars/asd.jpg",
                "text" : "....."
        }
        {
                "user" : "test",
                "avatar" : "/static/avatars/asd.jpg",
                "text" : "....."
        }
        ...
   ]
}

我正在尝试执行以下查询:

update({"comments.user":"test"},{$set:{"comments.$.avatar": "new_avatar.jpg"}},false,true)

问题是它更新了所有文档,但它只更新每个文档中的第一个数组元素。有没有办法更新所有数组元素,或者我应该尝试手动更新?谢谢。

4

4 回答 4

20

您不能在单个更新操作中修改多个数组元素。因此,您必须重复更新才能迁移需要修改多个数组元素的文档。您可以通过遍历集合中的每个文档,重复应用更新来做到这一点,$elemMatch直到文档的所有相关注释都被替换,例如:

db.collection.find().forEach( 函数(doc) {
  做 {
    db.collection.update({_id: doc._id,
                          评论:{$elemMatch:{用户:“测试”,
                                                头像:{$ne:"new_avatar.jpg"}}}},
                         {$set:{"comments.$.avatar":"new_avatar.jpg"}});
  } 而 (db.getPrevError().n != 0);
})

请注意,如果此操作的效率是您的应用程序的要求,您应该规范化您的架构,以便将用户头像的位置存储在单个文档中,而不是存储在每个评论中。

于 2013-02-06T07:49:28.250 回答
6

一种解决方案可能是创建一个与 forEach 一起使用的函数并对其进行评估(因此它运行得很快)。假设您的收藏是“文章”,您可以运行以下命令:

var runUpdate = function(){
    db.article.find({"comments.user":"test").forEach( function(article) {
        for(var i in article.comments){
            article.comments[i].avatar = 'new_avatar.jpg';
        }
        db.article.save(article);
    });
};

db.eval(runUpdate);
于 2013-02-06T03:45:19.047 回答
1

如果您知道要更新的索引,则可以毫无问题地执行此操作:

var update = { $set: {} };
for (var i = 0; i < indexesToUpdate.length; ++i) {
  update.$set[`comments.${indexesToUpdate[i]}. avatar`] = "new_avatar.jpg";
}
Comments.update({ "comments.user":"test" }, update, function(error) {
  // ...
});
  • 请注意,IDE 的 must 将不接受该语法,但您可以忽略它。
于 2016-01-26T11:47:43.847 回答
-1

看起来你可以这样做:

db.yourCollection.update({"comments.user":"test"},{$set:{"comments.0.avatar": "new_avatar.jpg", "comments.1.avatar": "new_avatar.jpg", etc...})

因此,如果您有少量已知的数组元素,这可能会更容易一些。如果你想要“comments.*.avatar”之类的东西 - 不知道该怎么做。你有这么多的数据重复可能不是那么好。

于 2014-03-22T07:29:31.600 回答