集計ビルダー
項目一覧
Overview
このガイドでは、Lambda 統合集計ビルダを使用して集計を実行し、パイプラインを構築する方法を学習できます。 集計ビルダーを使用すると、タイプセーフな構文を使用して MongoDB集計パイプラインを構築できます。
集計パイプラインとは、MongoDB database のデータに対して変換と計算を順番に実行し、その結果を新しいドキュメントまたはドキュメントのセットとして出力するデータ処理パイプラインです。
集計パイプラインは、集計ステージで構成されています。 集計ステージでは、演算子を使用して入力データを処理し、次のステージが入力として使用するデータを生成します。
Lambda MongoDB 集計ビルダを使用すると、集計ステージと集計パイプラインをビルドできます。 次のセクションでは、集計ビルダーを使用して集計パイプラインのステージを作成する方法の例を示します。
Tip
集計ビルダー機能は Lambda MongoDB バージョン4.3以降でのみ使用できます。 集計ビルダを使用せずに集計を実行する方法の詳細については、クエリ ビルダ ガイドの「集計」を参照してください。
集計ステージの作成
集計パイプラインを開始するには、Model::aggregate()
メソッドを呼び出します。次に、集計ステージ メソッドを集計、 ステージに必要なパラメーターを指定します。例、sort()
演算子メソッドを呼び出して $sort
ステージを構築できます。
集計ビルダーには、集計ステージを構築するためにインポートできる次の名前空間が含まれています。
MongoDB\Builder\Accumulator
MongoDB\Builder\Expression
MongoDB\Builder\Query
MongoDB\Builder\Type
このセクションでは、一般的な集計ステージの使用方法を示す次の例を紹介します。
MongoDB 集計演算子の詳細については、サーバー マニュアルの「集計ステージ」を参照してください。
サンプル ドキュメント
次の例では、 User
モデルで表されるコレクションに対して集計パイプラインを実行します。 次のinsert()
メソッドを実行してサンプル データを追加できます。
User::insert([ ['name' => 'Alda Gröndal', 'occupation' => 'engineer', 'birthday' => new UTCDateTime(new DateTimeImmutable('2002-01-01'))], ['name' => 'Francois Soma', 'occupation' => 'engineer', 'birthday' => new UTCDateTime(new DateTimeImmutable('1998-02-02'))], ['name' => 'Janet Doe', 'occupation' => 'designer', 'birthday' => new UTCDateTime(new DateTimeImmutable('1987-03-03'))], ['name' => 'Eliud Nkosana', 'occupation' => 'engineer', 'birthday' => new UTCDateTime(new DateTimeImmutable('1984-04-04'))], ['name' => 'Bran Steafan', 'occupation' => 'engineer', 'birthday' => new UTCDateTime(new DateTimeImmutable('1998-05-05'))], ['name' => 'Ellis Lee', 'occupation' => 'designer', 'birthday' => new UTCDateTime(new DateTimeImmutable('1996-06-06'))], ]);
マッチステージの例
クエリフィルターを指定するには、 match()
メソッドを集計パイプラインにチェーンできます。 このステージを省略すると、 aggregate()
メソッドは次の ステージのモデルの コレクション内のすべてのドキュメントを出力します。
この集計ステージは、利用可能なインデックスを使用してデータを取得し、後続のステージで処理されるデータ量を減らすために、多くの場合最初に配置されます。
Tip
match()
メソッドを省略すると、集計パイプラインは他の集計ステージの前のモデルに対応するコレクション内のすべてのドキュメントと一致します。
この例では、 MongoDB\Builder\Query
ビルダを使用して、一致集計ステージのクエリフィルターを構築します。 一致ステージには、次の条件が含まれます。
Query::or()
関数を使用して、クエリフィルターのいずれかに一致する結果を返しますoccupation
関数と 関数を使用して、値が である フィールドを含むドキュメントと一致させます"designer"
Query::query()
Query::eq()
name
関数と"Eliud Nkosana"
Query::query()
関数を使用して、 の値を持つ フィールドを含むドキュメントと一致させますQuery::eq()
コードの実行によって返されたドキュメントを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。
$pipeline = User::aggregate() ->match(Query::or( Query::query(occupation: Query::eq('designer')), Query::query(name: Query::eq('Eliud Nkosana')), )); $result = $pipeline->get();
[ { "_id": ..., "name": "Janet Doe", "occupation": "designer", "birthday": { "$date": { "$numberLong": "541728000000" } } }, { "_id": ..., "name": "Eliud Nkosana", "occupation": "engineer", "birthday": { "$date": { "$numberLong": "449884800000" } } }, { "_id": ..., "name": "Ellis Lee", "occupation": "designer", "birthday": { "$date": { "$numberLong": "834019200000" } } } ]
Tip
Query::or()
関数は、 $or
MongoDB クエリ演算子に対応します。 この演算子の詳細については、サーバー マニュアルの$orを参照してください。
グループ ステージの例
group()
メソッドを集計パイプラインにチェーンして、計算を実行し、一般的なフィールド値でグループ化してデータの構造を変更できます。
この集計ステージは、後続のステージで処理されるデータを減らすために、多くの場合、一致ステージの直後に配置されます。
この例では、 MongoDB\Builder\Expression
ビルダを使用して、グループ集計ステージでグループキーを定義します。 グループ ステージでは、次のグループ化動作を指定します。
_id
フィールドで表されるグループ キーの値を、Expression
ビルダで定義されたフィールド値に設定しますExpression::fieldPath()
関数を呼び出して、occupation
フィールドのドキュメント値を参照します
コードの実行によって返されたドキュメントを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。
$pipeline = User::aggregate() ->group(_id: Expression::fieldPath('occupation')); $result = $pipeline->get();
[ { "_id": "engineer" }, { "_id": "designer" } ]
Tip
このサンプル ステージでは、 distinct()
クエリ ビルダ メソッドと同様のタスクを実行します。 distinct()
メソッドの詳細については、「個別のフィールド値の取得」の使用例を参照してください。
ソート ステージの例
ドキュメントの出力順序を指定するには、 sort()
メソッドを集計パイプラインにチェーンできます。
この集計ステージは、パイプラインのどこにでも追加できます。 グループ化されたデータに依存する可能性があるため、グループ ステージの後に配置されることが多い。 処理されるデータを制限するために、ソート ステージを可能な限りパイプラインの末尾に配置することをお勧めします。
並べ替えを指定するには、フィールド値を 昇順ソート の場合はSort::Asc
列挙型に設定し、降順ソートの場合はSort::Desc
列挙型に設定します。
この例では、ドキュメントをname
フィールドでSort::Desc
にソートするsort()
集計パイプライン ステージが示されています。これはアルファベットの逆順に対応します。 コードの実行によって返されたドキュメントを確認するには、 VIEW OUTPUTボタンをクリックします。
$pipeline = User::aggregate() ->sort(name: Sort::Desc); $result = $pipeline->get();
[ { "_id": ..., "name": "Janet Doe", "occupation": "designer", "birthday": { "$date": { "$numberLong": "541728000000" } } }, { "_id": ..., "name": "Francois Soma", "occupation": "engineer", "birthday": { "$date": { "$numberLong": "886377600000" } } }, { "_id": ..., "name": "Ellis Lee", "occupation": "designer", "birthday": { "$date": { "$numberLong": "834019200000" } } }, { "_id": ..., "name": "Eliud Nkosana", "occupation": "engineer", "birthday": { "$date": { "$numberLong": "449884800000" } } }, { "_id": ..., "name": "Bran Steafan", "occupation": "engineer", "birthday": { "$date": { "$numberLong": "894326400000" } } }, { "_id": ..., "name": "Alda Gröndal", "occupation": "engineer", "birthday": { "$date": { "$numberLong": "1009843200000" } } } ]
プロジェクト ステージの例
project()
メソッドを集計パイプラインにチェーンして、このステージで表示するドキュメントのフィールドを指定できます。
含めるフィールドを指定するには、フィールドの名前と1
やtrue
などの真実の値を渡します。 他のすべてのフィールドは出力から省略されます。
あるいは、除外するフィールドを指定するには、各フィールド名と誤った値( 0
やfalse
など)を渡します。 他のすべてのフィールドは出力に含まれます。
Tip
含めるフィールドを指定すると、 _id
フィールドがデフォルトで含まれます。 _id
フィールドを除外するには、プロジェクション ステージで明示的に除外します。
この例では、 project()
メソッド集計ステージを使用してname
フィールドのみを含め、他のすべてのフィールドを出力から除外する方法を示します。 コードの実行によって返されたデータを確認するには、 VIEW OUTPUTボタンをクリックします。
$pipeline = User::aggregate() ->project(_id: 0, name: 1); $result = $pipeline->get();
[ { "name": "Alda Gröndal" }, { "name": "Francois Soma" }, { "name": "Janet Doe" }, { "name": "Eliud Nkosana" }, { "name": "Bran Steafan" }, { "name": "Ellis Lee" } ]
Aggregation Pipeline をビルドする
集計パイプラインを構築するには、Model::aggregate()
メソッドを呼び出し、集計ステージを実行する順序で連鎖させます。このセクションの例は、サーバー マニュアルを使用しています。各例には、データベースに挿入して集計操作をテストできるサンプルデータへのリンクが記載されています。
このセクションでは、一般的な集計ステージの使用方法を示す次の例を紹介します。
フィルターとグループの例
この例では、サーバー $group
マニュアルの ステージ参照の 「カウント、合計、平均の計算」セクションに記載されているサンプルデータを使用します。
次のコード例では、2014 年 の各日の合計売上額、平均売上数量、売上件数を計算します。そのために、次のステージを含む集計パイプラインを使用します。
$match ステージ:
date
年が である フィールドを含むドキュメントをフィルタリングします2014ドキュメントを日付別にグループ化し、各グループの合計売上額、平均売上数量、売上件数を計算する $group ステージ
$sort ステージ: 結果を各グループの合計売上額の降順でソートします
コードの実行によって返されるデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。
$pipeline = Sale::aggregate() ->match( date: [ Query::gte(new UTCDateTime(new DateTimeImmutable('2014-01-01'))), Query::lt(new UTCDateTime(new DateTimeImmutable('2015-01-01'))), ], ) ->group( _id: Expression::dateToString(Expression::dateFieldPath('date'), '%Y-%m-%d'), totalSaleAmount: Accumulator::sum( Expression::multiply( Expression::numberFieldPath('price'), Expression::numberFieldPath('quantity'), ), ), averageQuantity: Accumulator::avg( Expression::numberFieldPath('quantity'), ), count: Accumulator::sum(1), ) ->sort( totalSaleAmount: Sort::Desc, );
[ { "_id": "2014-04-04", "totalSaleAmount": { "$numberDecimal": "200" }, "averageQuantity": 15, "count": 2 }, { "_id": "2014-03-15", "totalSaleAmount": { "$numberDecimal": "50" }, "averageQuantity": 10, "count": 1 }, { "_id": "2014-03-01", "totalSaleAmount": { "$numberDecimal": "40" }, "averageQuantity": 1.5, "count": 2 } ]
埋め込まれた配列の展開例
この例では、サーバー $unwind
マニュアルの ステージ参照の 「埋め込み配列の展開」セクションに記載されているサンプルデータを使用します。
次のコード例では、販売された商品をタグごとにグループ化し、タグごとに合計販売額を計算します。そのために、次のステージを含む集計パイプラインを使用します。
$unwind ステージ: 配列の要素ごとに個別のドキュメントを出力
items
$unwind ステージ: 配列の各要素に対して個別のドキュメントを出力します
items.tags
$group ステージ: ドキュメントをタグの値でグループ化し、各タグを持つアイテムの合計売上額を計算します。
コードの実行によって返されるデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。
$pipeline = Sale::aggregate() ->unwind(Expression::arrayFieldPath('items')) ->unwind(Expression::arrayFieldPath('items.tags')) ->group( _id: Expression::fieldPath('items.tags'), totalSalesAmount: Accumulator::sum( Expression::multiply( Expression::numberFieldPath('items.price'), Expression::numberFieldPath('items.quantity'), ), ), );
[ { "_id": "school", "totalSalesAmount": { "$numberDecimal": "104.85" } }, { "_id": "electronics", "totalSalesAmount": { "$numberDecimal": "800.00" } }, { "_id": "writing", "totalSalesAmount": { "$numberDecimal": "60.00" } }, { "_id": "office", "totalSalesAmount": { "$numberDecimal": "1019.60" } }, { "_id": "stationary", "totalSalesAmount": { "$numberDecimal": "264.45" } } ]
単一の等価結合の例
この例では、サーバー $lookup
マニュアルの ステージ参照の 「$lookup を使用して単一の等価結合を実行する」セクションに記載されているサンプルデータを使用します。
次のコード例では、orders
コレクションの item
フィールドと inventory
コレクションの sku
フィールドを使用して、orders
コレクションのドキュメントと inventory
コレクションのドキュメントを結合します。
そのために、この例では、データを取得するコレクションとローカル フィールド名と外部フィールド名を指定する $lookup ステージを含む集計パイプラインを使用します。
コードの実行によって返されるデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。
$pipeline = Order::aggregate() ->lookup( from: 'inventory', localField: 'item', foreignField: 'sku', as: 'inventory_docs', );
[ { "_id": 1, "item": "almonds", "price": 12, "quantity": 2, "inventory_docs": [ { "_id": 1, "sku": "almonds", "description": "product 1", "instock": 120 } ] }, { "_id": 2, "item": "pecans", "price": 20, "quantity": 1, "inventory_docs": [ { "_id": 4, "sku": "pecans", "description": "product 4", "instock": 70 } ] }, { "_id": 3, "inventory_docs": [ { "_id": 5, "sku": null, "description": "Incomplete" }, { "_id": 6 } ] } ]
カスタム演算子ファクトリを作成する
集計ビルダー を使用して集計パイプラインを作成する場合、カスタム演算子ファクトリーで操作またはステージを定義できます。 カスタム演算子ファクトリーは、 集計パイプライン の式またはステージを返す関数です。 これらの関数を作成すると、コードの読みやすさと再利用を向上させることができます。
この例では、指定された日付フィールドから年を抽出する式を返すカスタム演算子ファクトリを作成して使用する方法を示します。
次の関数は、日付を含むフィールドの名前を受け入れ、日付から年を抽出する式を返します。
public function yearFromField(string $dateFieldName): YearOperator { return Expression::year( Expression::dateFieldPath($dateFieldName), ); }
サンプル集計パイプラインには、次のステージが含まれています。
addFields()
はカスタム演算子ファクトリー関数を呼び出して、birthday
フィールドから年を抽出し、それをbirth_year
フィールドに割り当てます。project()
は出力にname
フィールドとbirth_year
フィールドのみを含む
コードの実行によって返されるデータを確認するには、[ VIEW OUTPUT ] ボタンをクリックします。
$pipeline = User::aggregate() ->addFields(birth_year: $this->yearFromField('birthday')) ->project(_id: 0, name: 1, birth_year: 1);
[ { "name": "Alda Gröndal", "birth_year": 2002 }, { "name": "Francois Soma", "birth_year": 1998 }, { "name": "Janet Doe", "birth_year": 1987 }, { "name": "Eliud Nkosana", "birth_year": 1984 }, { "name": "Bran Steafan", "birth_year": 1998 }, { "name": "Ellis Lee", "birth_year": 1996 } ]