サーチ…
前書き
Aggregations
操作はデータレコードを処理し、計算結果を返します。集計操作では、複数の文書の値をグループ化し、グループ化されたデータに対してさまざまな操作を実行して単一の結果を返すことができます。 MongoDBは、アグリゲーションを実行する3つの方法であるアグリゲーションパイプライン、マップリダクション機能、および単一目的アグリゲーションメソッドを提供します。
Mongoマニュアルhttps://docs.mongodb.com/manual/aggregation/から
構文
- db.collection.aggregate(パイプライン、オプション)
パラメーター
パラメータ | 詳細 |
---|---|
パイプライン | アレイ(データ集約操作またはステージのシーケンス) |
オプション | ドキュメント(オプション、パイプラインが配列として存在する場合のみ使用可能) |
備考
MongoDBの集約フレームワークは、SQLの共通のGROUP BY
機能を実現するために使用されます。
すべての例について、名前付きtransactions
コレクションに以下の挿入を考慮してください。
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10, fee : 2});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 10, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
カウント
デビットとクレジットの取引件数はどのようにして得られますか?これを行う1つの方法は、以下のようにcount()
関数を使用することです。
> db.transactions.count({cr_dr : "D"});
または
> db.transactions.find({cr_dr : "D"}).length();
しかし、 cr_dr
upfrontの可能な値が分からなければどうでしょうか?ここでは集約フレームワークが機能します。以下の集計クエリを参照してください。
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr', // group by type of transaction
// Add 1 for each document to the count for this type of transaction
count : {$sum : 1}
}
}
]
);
結果は
{
"_id" : "C",
"count" : 3
}
{
"_id" : "D",
"count" : 5
}
和
amount
の合計を得る方法は?以下の集合クエリを参照してください。
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1}, //counts the number
totalAmount : {$sum : '$amount'} //sums the amount
}
}
]
);
結果は
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 120.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 410.0
}
amount
とfee
を合計する別のバージョン。
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1},
totalAmount : {$sum : { $sum : ['$amount', '$fee']}}
}
}
]
);
結果は
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 128.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 422.0
}
平均
デビットとクレジットの取引の平均金額を取得する方法は?
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr', // group by type of transaction (debit or credit)
count : {$sum : 1}, // number of transaction for each type
totalAmount : {$sum : { $sum : ['$amount', '$fee']}}, // sum
averageAmount : {$avg : { $sum : ['$amount', '$fee']}} // average
}
}
]
)
結果は次のとおりです。
{
"_id" : "C", // Amounts for credit transactions
"count" : 3.0,
"totalAmount" : 128.0,
"averageAmount" : 40.0
}
{
"_id" : "D", // Amounts for debit transactions
"count" : 5.0,
"totalAmount" : 422.0,
"averageAmount" : 82.0
}
配列の操作。
配列内のデータエントリを処理する場合は、最初に配列を巻き戻す必要があります。アンワインド操作では、配列内の各エントリのドキュメントが作成されます。大規模な配列を持つドキュメントがたくさんある場合、ドキュメントの数が爆発的に増加します。
{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
db.inventory.aggregate( [ { $unwind : "$sizes" }] )
重要な注意点は、文書に配列が含まれていない場合、その文書は失われます。 mongo 3.2以降では、unwindオプション "preserveNullAndEmptyArrays"が追加されています。このオプションは、配列が見つからないときにドキュメントが保持されるようにします。
{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
{ "_id" : 3, "item" : "myItem3" }
db.inventory.aggregate( [ { $unwind : { path: "$sizes", includeArrayIndex: "arrayIndex" } }] )
一致
従業員の平均年齢が$ 70000以下のすべての部門を取得するためのクエリを書く方法は35以上ですか?
そのためには、70000ドル以下の給与を持つ従業員と照合するためのクエリを作成する必要があります。次に、集計ステージを追加して、部署別従業員をグループ化します。次に、average_ageという名前のフィールドを持つアキュムレータを追加して、$ avgアキュムレータを使用して部門ごとの平均年齢を検索し、既存の$ matchおよび$ group aggregatesの下に別の$ matchアトリビュートを追加して、average_age 35より大きいか等しい。
db.employees.aggregate([
{"$match": {"salary": {"$lte": 70000}}},
{"$group": {"_id": "$dept",
"average_age": {"$avg": "$age"}
}
},
{"$match": {"average_age": {"$gte": 35}}}
])
結果は次のとおりです。
{
"_id": "IT",
"average_age": 31
}
{
"_id": "Customer Service",
"average_age": 34.5
}
{
"_id": "Finance",
"average_age": 32.5
}
コレクション内に重複したフィールドを持つドキュメントを削除する(重複排除)
allowDiskUse:trueオプションはオプションですが、コレクションサイズが大きい場合はこの集約がメモリ集約型操作になる可能性があるため、メモリ不足を緩和するのに役立ちますので、常に使用することをお勧めします。
var duplicates = [];
db.transactions.aggregate([
{ $group: {
_id: { cr_dr: "$cr_dr"},
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}
},
{ $match: {
count: { "$gt": 1 }
}}
],allowDiskUse: true}
)
.result
.forEach(function(doc) {
doc.dups.shift();
doc.dups.forEach( function(dupId){
duplicates.push(dupId);
}
)
})
// printjson(duplicates);
// Remove all duplicates in one go
db.transactions.remove({_id:{$in:duplicates}})