配列の全要素の出現頻度をカウントするMongoDBクエリの書き方
MongoDBで配列内の各要素が何回出現するかを集計したい場合、aggregate()メソッドと$sum演算子を組み合わせることで実現できます。この記事では、実際のコード例を使いながら、配列要素の頻度をカウントする手順を詳しく解説します。
1. サンプルコレクションの作成
まずは、名前の配列を持つドキュメントを含むコレクションを作成しましょう。insertOne()メソッドを使ってドキュメントを挿入します。
> db.demo184.insertOne({"Names":["Chris","David","Bob"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e3999fb9e4f06af55199805")
}
> db.demo184.insertOne({"Names":["Chris","Mike"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e399a0d9e4f06af55199806")
}
> db.demo184.insertOne({"Names":["Chris","Bob","Carol"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e399a209e4f06af55199807")
}
この例では、「Names」というフィールドに名前の配列を持つ3つのドキュメントを作成しました。
2. コレクション内のドキュメントを確認
find()メソッドを使用して、コレクション内のすべてのドキュメントを表示します。
> db.demo184.find();
実行すると、以下のような出力が得られます。
{ "_id" : ObjectId("5e3999fb9e4f06af55199805"), "Names" : [ "Chris", "David", "Bob" ] }
{ "_id" : ObjectId("5e399a0d9e4f06af55199806"), "Names" : [ "Chris", "Mike" ] }
{ "_id" : ObjectId("5e399a209e4f06af55199807"), "Names" : [ "Chris", "Bob", "Carol" ] }
3. 各要素の頻度をカウントするクエリ
ここからが本題です。以下のクエリを実行すると、配列内のすべての要素について出現回数を集計できます。
> db.demo184.aggregate([
... { "$unwind" : "$Names" },
... { "$group": { "_id": "$Names", "count": { "$sum": 1} } },
... { "$group": {
... "_id": null,
... "counts": {
... "$push": {
... "k": "$_id",
... "v": "$count"
... }
... }
... } },
... { "$replaceRoot": {
... "newRoot": { "$arrayToObject": "$counts" }
... } }
...])
4. 実行結果
上記のクエリを実行すると、次のような結果が出力されます。
{ "Carol" : 1, "David" : 1, "Chris" : 3, "Bob" : 2, "Mike" : 1 }
この結果から、「Chris」が3回、「Bob」が2回、「Carol」「David」「Mike」がそれぞれ1回出現していることがわかります。
クエリの仕組みを解説
この集計パイプラインは、複数のステージを順番に処理することで目的の結果を得ています。各ステージの役割は以下の通りです。
$unwind ステージ
「Names」配列を分解し、配列の要素ごとに個別のドキュメントを生成します。これにより、各名前が1つのドキュメントとして扱えるようになります。
$group ステージ(第1段階)
「$sum: 1」を使って、同じ名前ごとにドキュメント数を合計します。この時点で「Chris: 3」「Bob: 2」のような形式で、各要素の出現回数が求まります。
$group ステージ(第2段階)と $push
すべての結果を1つのドキュメントにまとめます。「k」と「v」のペアでデータを押し込む($push)ことで、後続の変換処理に備えます。
$replaceRoot と $arrayToObject
$arrayToObject演算子を使ってキーと値のペアの配列をオブジェクト形式に変換し、$replaceRootで出力ドキュメントのルートとして設定します。これにより、「{"Chris": 3, ...}」のように読みやすい最終結果が得られます。
まとめ
MongoDBで配列要素の頻度をカウントするには、$unwind → $group → $arrayToObjectという流れのパイプラインを構築するのが定石です。この手法は、タグの集計やユーザーの興味分析など、さまざまなシーンで応用できるので、ぜひ活用してみてください。
-
MongoDBで配列の要素を1つだけ取得する方法|$slice演算子の使い方
MongoDBの$sliceで配列の要素を1つだけ取得する配列から特定の件数の要素だけを取り出したい場合、MongoDBでは$slice演算子を使用します。$sliceはプロジェクション演算子の一種で、指定した件数分の配列要素のみを返すことができます。ここでは、実際にコレクションを作成し、$sliceを使って配列の先頭1件だけを取得する手順を順番に見ていきましょう。サンプルデータの作成まず、insertOne()メソッドを使ってドキュメントをコレクションに挿入します。> db.demo579.insertOne( ... { ... _id : 101, ...
-
MongoDBで配列要素の平均値を取得するクエリの書き方
MongoDBで配列内の数値の平均を求める方法MongoDBでは、配列に格納された複数の数値から平均値を算出したいケースがよくあります。例えば、1つのドキュメントの中に複数の点数(Marks)が配列として保存されている場合、その平均点を取得したいことがあります。このような場合、集計パイプライン(aggregation)と$avg演算子を組み合わせることで、簡単に平均値を求めることができます。$avgは、指定したフィールド(配列の場合はその全要素)の数値の平均を自動的に計算してくれる便利な演算子です。以下、具体的な手順を見ていきましょう。1. コレクションを作成し、ドキュメントを挿入するまず、i