この章では、MongoDBの統計解析について詳しく説明します。主に集計パイプラインを使用して行われ、SQLの「group by」ステートメントに類似しています。MongoDBシェルでは、統計解析はdb.collection.aggregate()
関数を使用して実装されます。
前提チュートリアル
一般的な手順
-
$match
を使用して対象データをフィルタリングする -
$group
を使用してデータをグループ化し、計算する - 結果をソートするために
$sort
を使用する(オプション)
テストデータ
orders
コレクション内のデータは以下のようになります
{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 }
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 }
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 }
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 }
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }
aggregate 関数
db.collection.aggregate(pipeline)
説明:
-
pipeline
は配列パラメータを取り、各要素が処理段階を表します。
例
db.orders.aggregate([
{ $match: { status: "A" } }, // 最初の段階
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, // 2番目の段階
{ $sort: { total: -1 } } // 3番目の段階
])
同等なSQL
select sum(amount) as total from orders
where status="A"
group by cust_id
order by total desc
$match 段階
フォーマット:
{ $match: { <query> } }
説明:
-
<query>
MongoDBのクエリ条件
クエリ条件を設定するために使用します。$match
が無視された場合、すべてのデータのクエリを意味します。
ヒント: MongoDBのクエリ構文に馴染みがない場合は、以前の章を参照してください。
$group 段階
SQLのgroup by
句に類似し、データをグループ化した後、グループ化されたデータに対して一連の統計計算を実行するために使用されます。
$group の基本的な使用方法
構文:
{
$group:
{
_id: <expression>, // グループ化条件、例: どのフィールドでグループ化するか
<field1>: { <accumulator1> : <expression1> }, // 集計操作、N個の集計操作を追加できます
...
}
}
説明:
-
- カスタム統計指標の名前、合計でN個ある可能性があります -
- 集計関数、SQLのsum、avgなどの集計関数に似ていますが、MongoDBの集計関数はプレフィックスに$を付けたものです。例: $sum、$avg -
- 集計関数のパラメータで、通常はカウントするフィールドの値です。ドキュメントのフィールドを参照する場合は"$field name"の形式を使用します
例:
db.orders.aggregate([
{
$group: {
_id: "$cust_id",
total: { $sum: "$amount" }, // 最初の計算指標であるtotalを追加し、$sumの合計演算子を使用
amount_avg: {$avg: "$amount"} // 2番目の計算指標であるavgを追加し、$avgの平均計算演算子を使用
}
}
])
出力:
{ "_id" : "abc1", "total" : 75, "amount_avg" : 37.5 }
{ "_id" : "xyz1", "total" : 250, "amount_avg" : 83.33333333333333 }
同等なSQL:
select
sum(amount) as total,
avg(amount) as amount_avg
from orders
group by cust_id
$group 集計関数
$group でよく使用される集計関数は以下の通りです:
Operator | 説明 | 例 |
---|---|---|
$avg | 平均を計算する | {$avg: "$amount"} |
$sum | 合計 | {$sum: "$amount"} |
$max | 最大値 | {$max: "$amount"} |
$min | 最小値 | {$min: "$amount"} |
$first | グループ化後のデータを返す、最初のドキュメントの内容 | {$first: "$amount"} |
$last | グループ化後のデータを返す、最後のドキュメントの内容 | {$last: "$amount"} |
$push | グループ化後のデータを返す | { $push: { ord_date: "$ord_date", amount: "$amount" } |
$addToSet | グループ化後のデータを返す、$push と異なり重複を取り除く | { $addToSet: "$amount" } |
$push の例
db.orders.aggregate(
[
{
$group:
{
_id: "$cust_id",
all: { $push: { ord_date: "$ord_date", amount: "$amount" } } // ord_date と amount フィールドの値
}
}
]
)
出力
{ "_id" : "abc1", "all" : [ { "ord_date" : "2021-04-18 00:00:00", "amount" : 50 }, { "ord_date" : "2021-04-21 00:00:00", "amount" : 25 } ] }
{ "_id" : "xyz1", "all" : [ { "ord_date" : "2021-04-18 00:00:00", "amount" : 100 }, { "ord_date" : "2021-04-20 00:00:00", "amount" : 25 }, { "ord_date" : "2021-04-21 00:00:00", "amount" : 125 } ] }
$addToSet の例
db.orders.aggregate(
[
{
$group:
{
_id: "$cust_id",
all_amount: { $addToSet: "$amount" } // すべての重複のない amount の値を返す
}
}
]
)
出力
{ "_id" : "abc1", "all_amount" : [ 25, 50 ] }
{ "_id" : "xyz1", "all_amount" : [ 100, 25, 125 ] }
$sort:
$sort ステージは通常、集計されたデータを並べ替えるために最後に配置されます。
フォーマット:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
説明:
-
, - 並べ替えるフィールドの名前、複数のフィールドをサポートします。 -
- 並べ替えの方向、降順には -1、昇順には 1 を使用します。
例:
db.orders.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
])
集計ページネーション
$limit および $skip オペレータを使用してページネーションを実装できます。
例:
db.orders.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } },
{ $limit: 5 }, // 返されるレコードの数を制限します、ページネーションのページサイズに類似しています。
{ $skip: 1 } // 一定数のレコードをスキップします、SQL のオフセットに類似しています。
])