まず第一に、「ユーザークラスの辞書」は良い考えではありません。なぜ?追加のレートオブジェクトを追加するには、新しいアイテムを配列にプッシュする必要があります。これは、古いアイテムが削除されることを意味します。この挿入は、いわゆる「ドキュメントの移動」です。 "。ドキュメントの移動は遅く、MongoDBは空のスペースの再利用があまり得意ではないため、ドキュメントを大量に移動すると、大量の空のデータファイルが生成される可能性があります(「MongoDBTheDefinitiveGuide」ブックの一部のテキスト)。
次に、正しい解決策は何ですか。Blogsという名前のコレクションがあり、ブログ投稿の評価ソリューションを実装し、さらにすべてのユーザーベースの評価操作を追跡するとします。
ブログドキュメントのスキーマは次のようになります。
{
_id : ....,
title: ....,
....
rateCount : 0,
rateValue : 0,
rateAverage: 0
}
このドキュメントスキーマを含む別のコレクション(レート)が必要です:
{
_id: ....,
userId: ....,
postId:....,
value: ..., //1 to 5
date:....
}
そして、そのための適切なインデックスを定義する必要があります:
db.Rates.ensureIndex({userId : 1, postId : 1})// very useful. it will result in a much faster search operation in case you want to check if a user has rated the post previously
ユーザーが評価したい場合は、まず、ユーザーが投稿を評価したかどうかを確認する必要があります。ユーザーが'user1'
であると想定します 、クエリは次のようになります
var ratedBefore = db.Rates.find({userId : 'user1', postId : 'post1'}).count()
そしてratedBefore
に基づく 、 !ratedBefore
の場合 次に、新しいレートドキュメントをレートコレクションに挿入し、ブログのステータスを更新します。そうしないと、ユーザーは評価できません
if(!ratedBefore)
{
var postId = 'post1'; // this id sould be passed before by client driver
var userId = 'user1'; // this id sould be passed before by client driver
var rateValue = 1; // to 5
var rate =
{
userId: userId,
postId: postId,
value: rateValue,
date:new Date()
};
db.Rates.insert(rate);
db.Blog.update({"_id" : postId}, {$inc : {'rateCount' : 1, 'rateValue' : rateValue}});
}
次に、rateAverage
はどうなりますか ?rateCount
に基づいて計算することを強くお勧めします およびrateValue
クライアント側では、rateAverage
を簡単に更新できます mongoquery
を使用 、しかしあなたはそれをすべきではありません。なぜ?簡単な答えは次のとおりです。これは、クライアントがこの種の作業を処理するのに非常に簡単な作業であり、すべてのブログドキュメントを平均化するには、不要な更新操作が必要です。
平均クエリは次のように計算されます:
var blog = db.Blog.findOne({"_id" : "post1"});
var avg = blog.rateValue / blog.rateCount;
print(avg);
このアプローチを使用すると、mongodbで最大のパフォーマンスが得られ、ユーザー、投稿、日付に基づいてすべてのレートを追跡できます。