1

検索した後、1 つのフィールドに対して複数の更新を実行する方法がわかりませんでした。

「タグ」配列フィールドを持つドキュメントがあります。更新を開始する前に、すべてのドキュメントにランダムなタグが付けられます。1 回の操作で、いくつかのタグを追加し、いくつかのタグを削除したいと考えています。

次の更新演算子は、「無効な修飾子が指定されました: $and」というエラーを返します。

    updateOperators: { "$and" : [
      { "$addToSet" : { "tags" : { "$each" : [ "tag_1" , "tag_2"]}}},
      { "$pullAll" : { "tags" : [ "tag_2", "tag_3"]}}]}  

    collection.update(query, updateOperators, multi=true)  

How do I both add and remove values to an array in a single operation, to multiple documents?

4

2 に答える 2

2

更新クエリでは必要ありませんが、$and更新で 2 つのフィールドを同時に更新することはできません。シェルで次のことを試してみるとわかるように:

db.test.update({}, { "$addToSet" : { "tags" : { "$each" : [ "tag_1" , "tag_2"]}}, 
                     "$pullAll"  : { "tags" : [ "tag_2", "tag_3"] }}, true, false)

Cannot update 'tags' and 'tags' at the same timeエラーメッセージが表示されます。では、これを達成する方法は?このスキーマでは、複数の操作でそれを行う必要があります。以下に示すように、新しい一括操作 APIを使用できます (シェル)。

var bulk = db.coll.initializeOrderedBulkOp();
bulk.find({ "tags": 1 }).updateOne({ "$addToSet": { "$each" : [ "tag_1" , "tag_2"]}});
bulk.find({ "tags": 1 }).updateOne({ "$pullAll": { "tags": [ "tag_2", "tag_3"] } });
bulk.execute();

または、casbah で DSL ヘルパーを使用します。

val bulk = collection.initializeOrderedBulkOperation
bulk.find(MongoDBObject("tags" -> 1)).updateOne($addToSet("tags") $each("tag_1", tag_2"))
bulk.find(MongoDBObject("tags" -> 1)).updateOne($pullAll("tags" -> ("tags_2", "tags_3")))
bulk.execute()

アトミックではなく、他に何も変更しようとしないという保証はありませんが、現在取得できる限り近いものです。

于 2014-08-13T08:07:47.923 に答える
1

Mongo はアトミックな更新を行うため、配列に必要なタグを作成して、配列全体を置き換えることができます。

これはタグの「バインドされていない」配列であるため、配列を使用してこれらの値をすべて一緒に格納しないことをお勧めします。バインドされていない配列により、ディスク上で移動が発生し、インデックスが更新され、OS と mongo が機能します。

代わりに、各タグを個別のドキュメントとして別のコレクションに格納し、関連するドキュメントの _id に基づいて「バケット」にする必要があります。

{_id : <_id> <key> <value>} - single docuemnt

これにより、db.collection.find({_id : /^<_id>/}) を使用して 1 人のユーザーのすべてのタグをクエリし、結果をバケット化できます。

于 2014-08-12T21:40:02.747 に答える