これは、賛成票と反対票を実装するための良い方法ではありません。集約フレームワークがドキュメントを更新するためのメカニズムではないことを除けば、実装したいロジックのために、それが解決策である可能性があると考えることに引き寄せられたようです。ただし、集計は更新されません。
あなたが望むものは、それを「質問」スキーマと呼ぶことができます。これは次のような構造です。
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"upvoted": [],
"downvoted": [],
"upvoteCount": 0,
"downvoteCount": 0
}
これは、アトミック更新でうまく機能し、同時にオブジェクトに関するステートフル情報を実際に提供できるものです。
「賛成」と「反対」の配列の場合、「ユーザー」の投票には同様の一意のObjectId値があると見なします。したがって、これから行うのは $push
または$pull
いずれかの配列から、およびこれらの各操作とともにカウンター値を「インクリメント/デクリメント」します。
これが賛成票に対してどのように機能するかを次に示します。
db.questions.update(
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"upvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
"downvoted": ObjectId("53f51c0a4ffa9b02cf01c075")
},
{
"$push": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
"$inc": { "upvoteCount": 1, "downvoteCount": -1 },
"$pull": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
}
)
db.questions.update(
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"upvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
},
{
"$push": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
"$inc": { "upvoteCount": 1 },
}
)
実際には、これは2つの操作であり、バルク操作AP で実行できます。 私も(おそらく本当に最善の方法ですが)、それはそれを意味します。最初のステートメントは、現在のユーザーが配列に「反対票」を記録しているドキュメントにのみ一致します。そのため、そのユーザーID値を「反対票」配列に「プッシュ」しました。存在しない場合、更新は行われません。ただし、それぞれの配列からプッシュとプルの両方を行うと同時に、カウンターフィールドを「インクリメント/デクリメント」します。
最初のステートメントが一致しなかったものにのみ一致する2番目のステートメントを使用して、「反対票」に触れる必要がなく、賛成票のフィールドを処理するだけでよいという公正な評価を行います。どちらの場合も、安全な方法は、主な条件が現在のユーザーID値が「賛成」配列に存在しないことを確認することです。
反対票の場合、フィールドは逆になります:
db.questions.update(
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"downvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
"upvoted": ObjectId("53f51c0a4ffa9b02cf01c075")
},
{
"$pull": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
"$inc": { "upvoteCount": -1, "downvoteCount": 1 },
"$push": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
}
)
db.questions.update(
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"downvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
},
{
"$push": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
"$inc": { "downvoteCount": 1 },
}
)
当然、問題のユーザーの「賛成/反対」をキャンセルするだけの論理的な進行を見ることができます。また、必要に応じて賢く、クライアントの情報を公開して、現在のユーザーがすでに「賛成/反対」しているかどうかを表示するだけでなく、クリックアクションを制御し、不要なリクエストを排除することもできます。