あなたは、あなたがする必要のある操作を正しく特定することによって、そこへの道の一部でした。ただし、もちろん $ sort
$addToSetの有効な修飾子ではありませんコード>
MongoDBのマントラは「セットは注文されたとは見なされない」であるため :
エラーによって示されるここでの他の問題は、複数の更新演算子( $ addToSet
など)を使用できないことです。 および $ push
)同時にプロパティへの同じパス上。実際、さまざまな更新演算子の実行には「順序がない」ため、 $ addToSet
が保証されるわけではありません。 $ push
の前に発生します 。実際、それらは並行して動作している可能性が高いため、エラーが発生し、これは許可されません。
もちろん、その答えは「2つの」更新ステートメントです。 $ addToSet
用に1つ 1つは$sort
を適用するためのものです $eachを介して空の配列を「プッシュ」する
、
ただし、各更新が完了するのを本当に「待つ」必要はないため、これが「バルク」操作APIの目的です。したがって、両方の命令を1つでサーバーに送信できます。 1つを送信して取得する 応答:
var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({ "name": "Risas" }).update({
"$addToSet": {
"propiedades": { "name": "cola", "cantidad": 1 }
}
});
bulk.find({ "name": "Risas" }).update({
"$push": {
"propiedades": {
"$each": [ ], "$sort": { "cantidad": -1 }
}
}
});
bulk.execute();
したがって、これは実際にはサーバーへの1つの要求と1つの応答だけです。それはまだ「2つの」操作ですが、オーバーヘッドと、いくつかのスレッドがupadteの中間状態を取得する可能性は無視できます。
このアプローチの代替手段は、「セット検出」ロジックを .find()
に移動することです。 更新ステートメントの一部を適用してから、 $ push
を適用します。 「セット」に追加するメンバーがまだ存在しない場合:
var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({
"name": "Risas",
"propiedades": {
"$not": { "$elemMatch": { "name": "cola", "cantidad": 1 } }
}
}).update({
"$push": {
"propiedades": {
"$each": [{ "name": "cola", "cantidad": 1 }], "$sort": { "cantidad": -1 }
}
}
});
bulk.execute();
もちろん、ここで「複数の」配列要素を追加する場合は、それらをラップする必要があるという複雑な問題があります。 $ not
および $ elemMacth
$ and
でテストします
条件、そしてそれらの要素の「1つだけ」が有効である場合、それを単独で追加することはできません。
「最初に」「複数の」アイテムを使用してそのような操作を「試す」ことができますが、その後はすべきです 上記と同じロジックで個々の配列要素を「フォールバック」実行して、各要素の「プッシュ」の可能性を「テスト」します。
したがって、 $ addToSet
複数の配列エントリを使用すると、その2番目の部分が簡単になります。 1つのエントリに対して、「クエリ」と $ push
を実行するのは非常に簡単です。 、複数の場合、 $ addToSet
で「最初の」パターンを使用する方がおそらく短いパスです。 および$push
2番目のパターンを適用すると、とにかく複数の更新テストが行われるため、結果を「並べ替える」ための空の配列。