はじめに

今回は、MongodbのGroup by Multiple Fieldsを紹介します。 よりよく理解するために、まず集約関数について学びます。

MongoDB集計関数

集計関数はGROUP BY句で使われ、グループ化されたデータを集計するために使われます。 GROUP BY 句で使用すると、集計関数はより良いパフォーマンスを発揮します。 ただし、集約関数の使用はグループ化されたクエリに限定されるものではありません。

GROUP BY 句を使用しないクエリで集約関数が使用された場合、集約関数は結果セット全体(WHERE 句に一致するすべての行)を集約します。 GROUP BY句を使用しない場合、SELECTリストの一部の集約関数は、他の集約関数と一緒にしか使用できません。 そのため、集約関数は SELECT リストのリストに接続するために GROUP BY 句を使用する必要があります。

たとえば、GROUP BY 句を使用する代わりに、SELECT リストの AVG は SUM にのみ対応できますが、特定の列に対応できません。

MongoDB集約操作はデータに対するバッチ処理で使用されます。 コレクションを条件によってグループ化した後、sumやaverageなどの一連の操作を行います。 集計操作は、特に数学の統計やデータマイニングのための複雑なコレクション操作を行うことができます。

MongoDB の集約操作の入力は、コレクションドキュメントです。 出力は 1 つまたは複数のドキュメントになります。 MongoDB は非常に強力な集約操作を提供しており、次の3つのカテゴリーに分けられます。

  • Aggregation pipeline
  • Aggregation operation for single use
  • MapReduce programming model

Mongodb Group by Multiple Fields

$ group operator は新規ドキュメントを返す集約処理に使用されるものである。 これは独自の演算子を持っており、我々は$記号+フィールド名で現在のドキュメントのフィールドを取得することができます。 MongoDB の複数フィールドによるグループ化を理解するために、まず $ group で使えるすべての演算子のリストを見てみましょう。

  • $ sum – すべての数値フィールドの合計を返す
  • $ avg – 数値フィールド間の平均を計算する
  • $ min – 数値フィールドから最小値を返す
  • $ max – 数値フィールドから最大値を取得する – 数値フィールドの最大値を取得する。
  • $ push – フィールドの値を結果フィールドに挿入する
  • $ addToSet – 値を結果ドキュメントの配列に挿入するが、重複を作らない
  • $ first – 通常ソートのために、グループ化したものから最初のドキュメントのみを取得する。
  • $ last – 最後のドキュメントを返す。

集計パイプライン

マルチスレッドの POSIX モードでは、データ要素のストリームが指定した順序でスレッドのセットによって順次実行されるパイプラインという方法がある。集計パイプラインはステージから構成されている。 あるステージで文書を処理した後、集約パイプラインは処理結果を次のステージに転送する。

ポリマーチューブ機能 ドキュメントをフィルタリングして、条件に合うドキュメントを探します。 文書を変換し、文書の出力形式を変更する。

集計パイプラインの各レベルはステージ演算子を用いて定義され、各ステージ演算子は式演算子を用いて各レベルの前に合計、平均、連結、改行などの計算を行うことができる。 結果は最後に返され、返された結果は直接出力するか、コレクションに保存することができます。

処理の流れ

  • Db.collection.aggregate () はデータ処理のために同時に複数のチャネルを使用することが可能です。
  • Db.collection.aggregate () は MongoDB のネイティブ操作を使用して効率的に集約し、カスタム JS ルーチンを記述しなくても SQL で GroupBy などの操作をサポートします。
  • パイプラインの各フェーズは 100 MB のメモリを制限しています。 単一ノードのパイプラインがこの制限を超えると、MongoDB はエラーを発生させます。 大量のデータを処理するには、allowDiskUse プロパティを true に設定して、集約パイプノードの一時ファイルにデータを書き込み、100 MB のメモリ制限を許可します。
  • Db.collection.aggregate () は一連のスライスに適用できますが、一連のスライスで結果が失われることはありません。 MapReduce は一連のスライスに適用することができ、結果は一連のスライスの中で失われます。
  • Db.collection.aggregate () はカーソルを返し、データはメモリに保存され、MongoShell として直接管理することができます。
  • db.collection.aggregate () の出力は1つのドキュメントにしか保存できず、BSON ドキュメントのサイズは16MBに制限されます。

グループ化メソッド

グループ化メソッドを使うのは SQL で GROUP BY 節を使うのに似ています。 groupメソッドには3つのパラメーターがあります:

  • Key: グループのキーを表示します
  • Initial: ドキュメントグループを表すドキュメントフィールドを初期化する
  • Reduce: 要素数を返す関数です。 この関数は2つのパラメータを引数として使用します:現在の要素と現在のグループの集約結果ドキュメントです。
  • Keyf: オプションのパラメータです。 戻り値のキーオブジェクトを表すために、key引数以外の関数を使用します。
  • Cond: オプションのパラメータです。 条件がtrueを返すべきであり、そうでなければドキュメントはグループ化に参加しないことを指定する。 このパラメータが指定されない場合、すべてのドキュメントがグループ化に参加します。
  • Finalize:オプションのパラメータです。

例:`js> db.users.group ({key: {name : true}, initial: {total : 0},reduce : function (curr, res){res.total += 1}})`

この式を見てみましょう。 keyパラメータは、グループが名前によってグループ化されることを指定します:key: {name: true}

initialパラメータの値は、グループの結果ドキュメントを表現するフィールドを初期化します。 この場合、totalフィールドの初期値が設定されます。 このフィールドは、グループ内の要素数を示す。 要素がない場合もあるので、0に初期化します。

reduceパラメータは、currパラメータがグループ内の現在のオブジェクトを指し、resが現在のグループを表す関数を表します。 nameフィールドに特定の値を持つ別のオブジェクトを見つけたら、そのドキュメントをグループに追加し、resドキュメントの合計値を1つ増やします。

$groupの使用

カスタムフィールド統計を使って、グループ化するキー名を指定するのに_idを使用します。 集約操作を使用すると、Mongodbの複数フィールドによるグループ化の概念がクリアされます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
db.users.aggregate({
$match : { age: { $gte : 18 }}. }
},{
$group : { _id:$username, count:{$sum:1}}. }
});
// Mongodb group by multiple fields
db.users.aggregate({
$match.Group});
// Mongodb group by multiple fields
db.users.aggregate({
$match: {age: {$gte:18} }},
$group: {_id:{username:$username, age:$ge}, ‘count’:{$sum:1}. }
})
// $sum:val 各文書にvalをつける
// $avg:val 各文書の値を平均する
db.users.aggregate({
$group: { _id:$username, count:{$avg:$age} }
})
db.users.aggregate({
$group: { _id:$username, count:{$max:$age} }
})
db.users.aggregate.{
$group: { _id:$username, count:{$vg:$ge} }$group: {_id:$username, count:{$min:$age} }
})
// $first:val グループ内で最初になる
db.users.aggregate({
$group:{_id:$username, count:{$first: $age} }
})
db.users.aggregate ({{666>$group: {_d: $username,}})
$group.group: {_d:user} }$group:{_id:$username, count:{$last: $age} }
})
db.users.aggregate({
$group: {_id:$username, count:{$addToSet: $age} }
})
db.users.aggregate.{
$group:{_ID:$1sername, count:$$last: $age} }
})
db.Users.aggregate({
$group:{_ID:$2sername: Count:{$last: $age} }
})aggregate({
$group:{_id:$username, count:{$push: $age} }
})

Mongodb group by multiple fields using Aggregate operation

まずグループ化の基になっているキーを選択し、そのキー値によってコレクションをグループに分割していくのですが、グループ化されたキーが選択したグループから外れると、グループ化されていないキーが選択したグループから外れることになります。 その後、各グループのドキュメントを集約して最終的なドキュメントを作成します。

グループはフラグメントクラスターをサポートせず、シャードクラスターを実行することはできません。 分散サポートが必要な場合は、aggregate または mapReduce を使用する必要があります。

1
2
3
4
5
7
8
9
10
11
12
13
db.collection.group(document)
{
# grouping field
key:{key1, key2:1},
# Query conditions
cond:{},
# Aggregate function
reduce:function(current, result){},
# initialization
initial:{},
# Counting Return Function Set
finalize:function(){}
},
># Counting Function Set

各列の個数を計算する

1
2
3
4
5
6
7
8
9
SELECT COUNT(*) FROM goods GROUP BY category_id.COUNT(*) FROM goods GROUP BY category_id.COUNT(*) GROUP BY category_id;
db.goods.group({
key:{category_id:1},
cond:{},// all together
reduce:function(current, result){// 現在の行に対応する,結果 グループの複数の行に対応する
result.total += 1;
},
initial:{total:0}
})

結論

この記事は、開発者が集約関数を使って複数のフィールドで Mongodb グループを理解するために書かれたものです。 もし、この記事が役に立つなら、Object Rocketを訪問して、もっと多くのデータベース関連記事を読んでください。

もし、データベースのセキュリティ、スケーラビリティ、バックアップの管理についてアドバイスやヘルプが必要な場合は、Object Rocketにご連絡ください。

コメントを残す

メールアドレスが公開されることはありません。