ドキュメント全体をどのように構成しても、基本的に2つのことが必要です。これは基本的に、重複が送信されないようにするために、すでに「いいね」を投稿した人の「カウント」と「リスト」のプロパティです。基本的な構造は次のとおりです。
{
"_id": ObjectId("54bb201aa3a0f26f885be2a3")
"photo": "imagename.png",
"likeCount": 0
"likes": []
}
いずれにせよ、あなたの「写真投稿」とあなたが望むどんな情報にもユニークな「_id」がありますが、それから前述のように他のフィールドがあります。ここでの「likes」プロパティは配列であり、システム内の「user」オブジェクトからの一意の「_id」値を保持します。したがって、すべての「ユーザー」は、ローカルストレージまたはOpenIdなどのどこかに独自の識別子を持っていますが、一意の識別子を持っています。 ObjectId
を使い続けます 例として。
誰かが投稿に「いいね」を送信した場合、次の更新ステートメントを発行する必要があります。
db.photos.update(
{
"_id": ObjectId("54bb201aa3a0f26f885be2a3"),
"likes": { "$ne": ObjectId("54bb2244a3a0f26f885be2a4") }
},
{
"$inc": { "likeCount": 1 },
"$push": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") }
}
)
今度は$inc
そこで操作すると、「likeCount」の値が指定された数だけ増加するため、1ずつ増加します。 $push
操作により、ユーザーの一意の識別子がドキュメント内の配列に追加され、後で参照できるようになります。
ここでの主な重要なことは、投票したユーザーと、ステートメントの「クエリ」部分で何が起こっているかを記録することです。独自の「_id」で更新するドキュメントを選択する以外に、他の重要なことは、「likes」配列をチェックして、現在の投票ユーザーがまだそこにいないことを確認することです。
逆の場合、または「いいね」を「削除」する場合も同様です。
db.photos.update(
{
"_id": ObjectId("54bb201aa3a0f26f885be2a3"),
"likes": ObjectId("54bb2244a3a0f26f885be2a4")
},
{
"$inc": { "likeCount": -1 },
"$pull": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") }
}
)
ここで最も重要なことは、すべての条件が満たされていない場合にドキュメントがタッチされないようにするために使用されるクエリ条件です。したがって、ユーザーがすでに投票している場合はカウントが増加せず、更新時に投票が実際に存在しなくなった場合はカウントが減少します。
もちろん、アプリケーションの他の部分に戻って、ドキュメント内の数百のエントリを含む配列を読み取ることは実用的ではありません。しかし、MongoDBにはそれを処理するための非常に標準的な方法もあります:
db.photos.find(
{
"_id": ObjectId("54bb201aa3a0f26f885be2a3"),
},
{
"photo": 1
"likeCount": 1,
"likes": {
"$elemMatch": { "$eq": ObjectId("54bb2244a3a0f26f885be2a4") }
}
}
)
この$elemMatch
の使用法 in Projectionは、現在のユーザーが存在する場合、または存在しない場合は空白の配列のみを返します。これにより、残りのアプリケーションロジックは、現在のユーザーがすでに投票したかどうかを認識できます。
これは基本的な手法であり、そのまま使用できる場合がありますが、埋め込み配列を無限に拡張してはならず、BSONドキュメントには16MBの厳しい制限があることに注意してください。したがって、コンセプトは健全ですが、コンテンツに数千の「いいね投票」を期待している場合は、それだけで使用することはできません。 「バケッティング」と呼ばれる概念があります。これは、ハイブリッドスキーマ設計のこの例で詳細に説明されており、1つのソリューションで大量の「いいね」を保存できます。これを大量に行う方法として、ここで基本的な概念とともに使用することを検討できます。