もちろん、ここで行っているのは、ドキュメントが更新または挿入されたかどうか、あるいは実際にはどちらの操作も行われなかったかどうかを示す応答を実際にチェックすることです。これは、 $addToSet
に関する最良の指標です。 更新を実行すると、ドキュメントが更新されます。
$addToSet
演算子自体は重複を生成できません。これが演算子の性質です。しかし、あなたは確かにあなたの論理にいくつかの問題を抱えているかもしれません:
{
"$addToSet", new BsonDocument()
{
{ "items", new BsonDocument()
{
{ "id", item.Id },
{ "v", item.Value }
}
}
}
}
つまり、「セット」内のアイテムが2つのフィールドで構成されていることを明確に示しているので、そのコンテンツが何らかの形で変化する場合(つまり、IDが同じで値が異なる場合)、アイテムは実際にはセットの「一意の」メンバーであり、追加されます。たとえば、 $addToSet
の方法はありません。 一意の識別子としての「id」のみに基づいて新しい値を追加しない演算子。実際にそれをコードでロールする必要があります。
ここでの重複の形式の2番目の可能性は、クエリ部分が更新する必要のあるドキュメントを正しく検出していないことです。この結果、「セット」に新しく指定されたメンバーのみを含む新しいドキュメントが作成されます。したがって、よくある使用上の間違いは次のようなものです。
db.collection.update(
{
"id": ABC,
"items": { "$elemMatch": {
"id": 123, "v": 10
}},
{
"$addToSet": {
"items": {
"id": 123, "v": 10
}
}
},
{ "upsert": true }
)
既存のドキュメントには「セット」に指定された要素が含まれていなかったため、この種の操作の結果は常に新しいドキュメントを作成します。正しい実装は、しないことです。 「set」メンバーの存在を確認し、 $addToSet
を許可します 仕事をするために。
確かにあなたが本当を持っているなら サブドキュメントのすべての要素が完全に同じである「セット」で発生する重複エントリは、現在または過去のいずれかの他のコードが原因で発生しています。
新しいエントリが作成されていることが確実な場合は、コードを調べて $push
のインスタンスを探します。 または実際、同じフィールドに作用しているように見えるコードでの配列操作。
ただし、演算子を正しく使用している場合は、 $addToSet
意図したとおりに動作します。