MongoDB更新了多个数组记录

时间:2013-02-06 02:43:41

标签: arrays mongodb

我最近开始使用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 个答案:

答案 0 :(得分:20)

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

db.collection.find().forEach( function(doc) {
  do {
    db.collection.update({_id: doc._id,
                          comments:{$elemMatch:{user:"test",
                                                avatar:{$ne:"new_avatar.jpg"}}}},
                         {$set:{"comments.$.avatar":"new_avatar.jpg"}});
  } while (db.getPrevError().n != 0);
})

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

答案 1 :(得分:5)

一个解决方案可能是创建一个与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);

答案 2 :(得分: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的必须不接受语法,但您可以忽略它。

答案 3 :(得分:-1)

好像你可以这样做:

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

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