MongoDBで重複するIDごとの評価(レーティング)平均を取得する方法
MongoDBで重複するIDごとの評価平均を取得する方法
MongoDBで平均値を計算するには、集計フレームワーク(Aggregation Pipeline)の $avg 演算子を使用します。本記事では、重複する id を持つドキュメントから、IDごとの評価(rating)の平均値を求める手順を、実際のコード例とともにわかりやすく解説します。
1. サンプルコレクションの作成
まず、insertOne() メソッドを使って、重複する id とそれぞれの評価値を持つドキュメントをコレクションに登録します。一部のドキュメントには評価として null が設定されている点に注目してください。
> db.demo606.insertOne({id:1,rating:5});{
"acknowledged" : true, "insertedId" : ObjectId("5e972dfbf57d0dc0b182d623")
}
> db.demo606.insertOne({id:1,rating:4});{
"acknowledged" : true, "insertedId" : ObjectId("5e972dfef57d0dc0b182d624")
}
> db.demo606.insertOne({id:2,rating:3});{
"acknowledged" : true, "insertedId" : ObjectId("5e972e09f57d0dc0b182d625")
}
> db.demo606.insertOne({id:1,rating:null});{
"acknowledged" : true, "insertedId" : ObjectId("5e972e0ef57d0dc0b182d626")
}
> db.demo606.insertOne({id:2,rating:null});{
"acknowledged" : true, "insertedId" : ObjectId("5e972e15f57d0dc0b182d627")
}
> db.demo606.insertOne({id:2,rating:3});{
"acknowledged" : true, "insertedId" : ObjectId("5e972e1bf57d0dc0b182d628")
}登録されたすべてのドキュメントを確認するには、find() メソッドを使用します。
> db.demo606.find();
実行すると、次のように6件のドキュメントが表示されます。
{ "_id" : ObjectId("5e972dfbf57d0dc0b182d623"), "id" : 1, "rating" : 5 }
{ "_id" : ObjectId("5e972dfef57d0dc0b182d624"), "id" : 1, "rating" : 4 }
{ "_id" : ObjectId("5e972e09f57d0dc0b182d625"), "id" : 2, "rating" : 3 }
{ "_id" : ObjectId("5e972e0ef57d0dc0b182d626"), "id" : 1, "rating" : null }
{ "_id" : ObjectId("5e972e15f57d0dc0b182d627"), "id" : 2, "rating" : null }
{ "_id" : ObjectId("5e972e1bf57d0dc0b182d628"), "id" : 2, "rating" : 3 }2. IDごとの評価平均を取得するクエリ
重複する id ごとに評価の平均値を求めるには、aggregate() メソッド内で $group ステージと $avg 演算子を組み合わせます。ポイントは、$ifNull を使って null 値を 0 に置き換えているところです。これにより、評価が未設定のドキュメントも平均計算の対象に含めることができます。
> db.demo606.aggregate(
... [
... { "$group": {
... "_id": "$id",
... "AverageRating": { "$avg": { "$ifNull": ["$rating",0 ] } }
... }}
... ]
... );このクエリを実行すると、次のような結果が得られます。
{ "_id" : 2, "AverageRating" : 2 }
{ "_id" : 1, "AverageRating" : 3 }3. 結果の解説
id が 1 のグループでは、評価は「5」「4」「null」の3件です。$ifNull によって null が 0 として扱われるため、(5 + 4 + 0) ÷ 3 = 3 という平均値が算出されます。
同様に、id が 2 のグループでは、評価は「3」「null」「3」の3件なので、(3 + 0 + 3) ÷ 3 = 2 となります。
補足:nullを除外して平均を求めたい場合
なお、MongoDBの $avg は通常、null や欠損フィールドなどの数値以外の値を自動的に無視します。つまり $ifNull を使わなければ、null のドキュメントは分子にも分母にも含まれません(例:id 1 の場合は (5 + 4) ÷ 2 = 4.5)。
一方、$ifNull で null を 0 に置き換えると、未評価のドキュメントも分母にカウントされます。用途に応じて、「未評価を0点として扱う」か「未評価を計算対象から外す」かを選択することが重要です。後者を明示的に行いたい場合は、$group の前に $match ステージを追加して、rating が null でないドキュメントのみを事前に絞り込むのも有効な方法です。
-
MongoDBで配列フィールドを使ってドキュメントをフィルタリングする方法($elemMatch演算子の使い方)
MongoDBで配列内の要素に基づいてドキュメントをフィルタリングしたい場合、$elemMatch 演算子を使用します。$elemMatch は、指定した条件を満たす要素を少なくとも1つ含む配列フィールドを持つドキュメントを照合するための演算子です。この記事では、実際にコレクションを作成し、$elemMatch を使って配列条件でドキュメントを絞り込む手順を解説します。サンプルコレクションの作成まず、テスト用のコレクションにドキュメントを挿入してみましょう。ここでは、学生の名前と点数(Marks)を持つ details 配列を含むドキュメントを作成します。> db.demo453.ins
-
MongoDBで配列の共通部分(交差)データを取得する方法
MongoDBで配列の共通部分を取得するには?MongoDBで配列同士の共通要素(交差)を求めたい場合、集計パイプラインである aggregate() 内で $setIntersection 演算子を使用します。この演算子は、指定した複数の配列に共通して含まれる要素だけを抽出し、重複を除いた配列として返してくれます。それでは、実際にドキュメントを含むコレクションを作成しながら確認していきましょう。1. サンプルコレクションの作成> db.demo625.insertOne( ... { ... Name: "John", ... M