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

1回の更新操作で複数の配列要素を変更することはできません。したがって、複数の配列要素を変更する必要があるドキュメントを移行するには、更新を繰り返す必要があります。これを行うには、コレクション内の各ドキュメントを繰り返し処理し、$elemMatchドキュメントの関連するコメントがすべて置き換えられるまで、で更新を繰り返し適用します。例:

db.collection.find()。forEach(function(doc){
  行う {
    db.collection.update({_ id:doc._id、
                          コメント:{$ elemMatch:{user: "test"、
                                                アバター:{$ ne: "new_avatar.jpg"}}}}、
                         {$ set:{"comments。$。avatar": "new_avatar.jpg"}});
  } while(db.getPrevError()。n!= 0);
})

この操作の効率がアプリケーションの要件である場合は、ユーザーのアバターの場所がすべてのコメントではなく単一のドキュメントに格納されるようにスキーマを正規化する必要があることに注意してください。

于 2013-02-06T07:49:28.250 に答える
6

1つの解決策は、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 に答える