私は C# ドライバー (NuGet の v1.8.3) を使用していますが、$addtoSet/upsert
操作によって実際に新しい項目が特定の配列に追加されたのか、それとも項目が既に存在していたのかを判断するのに苦労しています。
新しいアイテムの追加は、ドキュメントがまったく存在せず、アップサートによって作成されたばかりである場合と、ドキュメントは存在するが配列が存在しないか、指定されたアイテムが含まれていない場合の 2 つのケースに分類される可能性があります。
これを行う必要がある理由は、MongoDB にロードする大量のデータ セットがあり、処理中に壊れる可能性があるためです (すべきではありませんが、壊れる可能性があります)。これが発生した場合、ダウンストリーム処理を重複させずに最初からバックアップを開始できるようにする必要があります (処理を冪等に保ちます)。私のフローでは、項目が新しく追加されたと判断された場合、その項目のダウンストリーム処理をキューに入れます。ドキュメントに既に追加されていると判断された場合、それ以上のダウンストリーム作業は必要ありません。私の問題は、アイテムが配列に既に存在し、実際には何も変更されていない場合でも、呼び出しが 1 つのドキュメントを変更したという結果が常に返されることです。
C# ドライバー API に関する私の理解に基づいて、 を使用して呼び出しを行いWriteConcern.Acknowledged
、 をチェックして、WriteConcernResult.DocumentsAffected
実際にドキュメントが更新されたかどうかを確認できるはずです。
私の問題は、すべての場合において、書き込み懸念の結果が 1 つのドキュメントが更新されたことを返すことです。:/
これは、私のコードが呼び出しているドキュメントの例です。$addToSet
この特定のアイテムが「アイテム」リストに含まれている場合と含まれていない場合があります。
{
"_id" : "some-id-that-we-know-wont-change",
"items" : [
{
"s" : 4,
"i" : "some-value-we-know-is-static",
}
]
}
私のクエリは常に_id
、処理メタデータに基づいて既知の値を使用します。
var query = new QueryDocument
{
{"_id", "some-id-that-we-know-wont-change"}
};
私の更新は次のとおりです。
var result = mongoCollection.Update(query, new UpdateDocument()
{
{
"$addToSet", new BsonDocument()
{
{ "items", new BsonDocument()
{
{ "s", 4 },
{ "i", "some-value-we-know-is-static" }
}
}
}
}
}, new MongoUpdateOptions() { Flags = UpdateFlags.Upsert, WriteConcern = WriteConcern.Acknowledged });
if(result.DocumentsAffected > 0 || result.UpdatedExisting)
{
//DO SOME POST PROCESSING WORK THAT SHOULD ONLY HAPPEN ONCE PER ITEM
}
空のコレクションに対してこのコードを 1 回実行すると、ドキュメントが追加され、期待どおりの応答が得られます ( DocumentsAffected = 1
, UpdatedExisting = false
)。再度 (何度でも) 実行すると、ドキュメントは変更されていないため更新されていないように見えますが、結果は予期しないものになりました ( DocumentsAffected = 1
、UpdatedExisting = true
)。
DocumentsAffected = 0
ドキュメントが変更されていない場合、これは返されるべきではありませんか?
これらの呼び出しを 1 日に何百万回も行う必要があるため、このロジックをアイテムごとに複数の呼び出しに変えることをためらっています (最初にアイテムが指定されたドキュメント配列に存在するかどうかを確認し、次に追加/キューに入れるか、単にスキップします)すべて可能です。
これを1回の呼び出しで機能させる方法はありますか?