我最近开始使用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)
问题是它更新了所有文档,但它只更新了每个文档中的第一个数组元素。有没有办法更新所有数组元素或我应该尝试手动执行? 感谢。
答案 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) {
// ...
});
答案 3 :(得分:-1)
好像你可以这样做:
db.yourCollection.update({"comments.user":"test"},{$set:{"comments.0.avatar": "new_avatar.jpg", "comments.1.avatar": "new_avatar.jpg", etc...})
因此,如果您有一个已知数量很少的数组元素,这可能会更容易一些。如果你想要“评论。*。头像”之类的东西 - 不知道该怎么做。你有如此多的数据重复可能不是那么好......