English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

MongoDB 聚合

アグリゲーション操作はデータレコードを処理し、計算結果を返します。アグリゲーション操作は複数のドキュメントの値をグループ化し、グループ化されたデータに対して様々な操作を行い、単一の結果を返します。SQLでは、count(*)およびgroup byはMongoDBのアグリゲーションに相当します。

Aggregate()メソッド

MongoDBのアグリゲーションでは、以下を使用します aggregate() メソッド。

文法

aggregate()基本的な文法は以下の通りです-

>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

オンラインサンプル

コレクション内で、以下のデータがあります-

{
   _id: ObjectId(7df78ad8902c)
   title: 'MongoDB Overview', 
   description: 'MongoDBはSQLデータベースではありません',
   by_user: 'oldtoolbag.com,
   url: 'https://ja.oldtoolbag.com,
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: ObjectId(7df78ad8902d)
   title: 'NoSQL Overview', 
   description: 'No SQLデータベースは非常に高速です',
   by_user: 'oldtoolbag.com,
   url: 'https://ja.oldtoolbag.com,
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 10
},
{
   _id: ObjectId(7df78ad8902e)
   title: 'Neo4j 概要' 
   description: 'Neo4j はNo SQLデータベース
   by_user: 'Neo4j',
   url: 'http://www.neo4j.com',
   tags: ['neo4j', 'database', 'NoSQL'],
   likes: 750
},

現在、上記のコレクションから、各ユーザーがどれだけのチュートリアルを書いたかを表示するリストを表示する場合、以下を使用しますaggregate()メソッド-

> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{ "_id" : "oldtoolbag.com", "num_tutorial" : 2 }
{ "_id" : "Neo4j", "num_tutorial" : 1 }
>

以上の用例のSQL相当のクエリは、以下のようになります select by_user, count(*) from mycol group by by_user

上記の例では、フィールドby_userドキュメントに対してグループ化を行い、ユーザーごとにグループ化するたびに、前のsum値が増加します。以下に利用可能なアグリゲーション表現のリストがあります。

表現説明
$sum合計を計算します。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avg平均値を計算します。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$minコレクション内のすべてのドキュメントに対応する値の最小値を取得します。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$maxコレクション内のすべてのドキュメントに対応する値の最大値を取得します。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push結果ドキュメントに値を配列に挿入します。db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet結果ドキュメントに値を配列に挿入しますが、複製を作成しません。db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$firstリソースドキュメントのソートに基づいて最初のドキュメントデータを取得します。db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$lastリソースドキュメントのソートに基づいて最後のドキュメントデータを取得します。db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

パイプラインの概念

パイプラインはUnixやLinuxで一般的に使用され、現在のコマンドの出力結果を次のコマンドの引数として使用します。

MongoDBの聚合パイプラインは、MongoDBドキュメントを1つのパイプライン処理が完了した後に結果を次のパイプラインに渡し、パイプライン操作は繰り返し可能です。

表达式:入力ドキュメントを処理して出力します。表达式は無状態であり、現在の聚合パイプラインのドキュメントにのみ使用できますが、他のドキュメントを処理することはできません。

ここでは、聚合フレームワークでよく使用される操作のいくつかを紹介します:

  • $project:入力ドキュメントの構造を変更します。フィールドの名前の変更、追加、削除、計算結果の作成、ネストドドキュメントの作成に使用できます。

  • $match:データをフィルタリングし、条件に一致するドキュメントのみを出力します。$matchはMongoDBの標準のクエリ操作を使用します。

  • $limit:MongoDBの聚合パイプラインが返すドキュメント数を制限します。

  • $skip:聚合パイプラインで指定された数のドキュメントをスキップし、残りのドキュメントを返します。

  • $unwind:ドキュメント内の特定の配列型フィールドを複数の行に分割し、配列の各値を含む行を生成します。

  • $group:コレクション内のドキュメントをグループ化し、統計結果に使用できます。

  • $sort:入力ドキュメントをソートして出力します。

  • $geoNear:特定の地理的な位置に近い順序付けされたドキュメントを出力します。

パイプライン操作子インスタンス

1、$project インスタンス

db.article.aggregate(
    { $project : { }}
        title : 1 ,
        author : 1 ,
    }}
 );

このようにすると、結果には_id、title、authorの3つのフィールドだけが含まれます。デフォルトでは_idフィールドは含まれていますが、含めたくない場合は以下のようにできます:

db.article.aggregate(
    { $project : { }}
        _id : 0 ,
        title : 1 ,
        author : 1
    }});

2.$match インスタンス

db.articles.aggregate( [
                        { $match : { score : { $gt : 70, $lte : 90 } } },
                        { $group: { _id: null, count: { $sum: 1 } } }
                       ] );

$match はスコアが70が90レコード、そして次のステージ $group パイプライン操作子に適合するレコードを送信します。

3.$skip インスタンス

db.article.aggregate(
    { $skip : 5 });

スキップパイプライン操作子 $skip により、最初の5つのドキュメントが「フィルタリング」されます。