Overview
このガイドでは、Mongoid を使用して集計操作 を実行する方法を学習できます。
集計操作により MongoDB コレクション内のデータが処理され、計算結果が返されます。 クエリ API の一部である MongoDB 集計フレームワークは、データ処理パイプラインの概念をモデル化したものです。 ドキュメントは 1 つ以上の ステージを含むパイプラインに投入され、そこで集計結果に変換されます。
集計操作は、組み立てラインを持つ自動車工場と同様に機能します。 組立ラインには、特定のタスクを実行するための専用ツールを備えたステーションがあります。 たとえば、自動車をビルドする場合、組立ラインは フレームから始まります。 その後、自動車フレームが組み立てラインを通過するにつれて、各ステーションは個別の部分を組み立てます。 その結果は変換された最終製品、完成品です。
組立ラインは集計パイプラインを表し、個々のステーションは集計ステージを表し、専用ツールは式演算子を表し、完成品は集計結果を表します。
集計操作と検索操作の比較
次の表は、集計操作で実行できる操作と比較して、検索操作で実行できるさまざまなタスクを示しています。 集計フレームワークは、データを変換および操作するための拡張機能を提供します。
検索操作 | 集計操作 |
|---|---|
返す特定のドキュメントを選択して返す |
|
Mongoid ビルダ
Mongoid の高レベルのドメイン固有言語(DSL)を使用して、集計パイプラインを構築できます。 DSL は次の集計パイプライン演算子をサポートしています。
前述の演算子のいずれかを使用して集計パイプラインを作成するには、Criteria のインスタンスで対応するメソッドを呼び出します。 メソッドを呼び出すと、Criteriaインスタンスの pipeline アトリビューションに集計操作が追加されます。 集計パイプラインを実行するには、pipeline 属性の値を Collection#aggregate メソッドに渡します。
例
次の クラスによってモデル化されたドキュメントを含むコレクションを含むデータベースを考えてみましょう。
class Tour include Mongoid::Document embeds_many :participants field :name, type: String field :states, type: Array end class Participant include Mongoid::Document embedded_in :tour field :name, type: String end
この例では、Tour モデルはツアーの名前とそのパスを移動する州を表し、Participant モデルはツアーに参加している人の名前を表します。
次の例では、次の集計操作を使用して、参加者が訪問した州を出力する集計パイプラインを作成します。
matchは、participants.nameフィールドの値が"Serenity"であるドキュメントを検索しますunwindは、states配列フィールドを分解し、 配列内の各要素のドキュメントを出力します。groupは、ドキュメントをstatesフィールドの値でグループ化します。projectは、パイプラインに_idフィールドとstatesフィールドのみを返すように要求します。
criteria = Tour.where('participant.name' => 'Serenity'). unwind(:states). group(_id: 'states', :states.add_to_set => '$states'). project(_id: 0, states: 1) @states = Tour.collection.aggregate(criteria.pipeline).to_json
[{"states":["OR","WA","CA"]}]
ビルダを持たない集計
Collection#aggregate メソッドでは、集計操作の配列を渡すことで、対応するビルダ メソッドがない集計操作を実行できます。 このメソッドを使用して集計を実行すると、Mongoid::Document モデル インスタンスではなく、未加工の BSON::Document オブジェクトが返されます。
例
次の クラスによってモデル化されたドキュメントを含むコレクションを含むデータベースを考えてみましょう。
class Band include Mongoid::Document has_many :tours has_many :awards field :name, type: String end class Tour include Mongoid::Document belongs_to :band field :year, type: Integer end class Award include Mongoid::Document belongs_to :band field :name, type: String end
次の例では、 2000 以降でツアーがあり、少なくとも 1 が付与されているすべてのバンドを検索するための集計パイプラインを作成します。
band_ids = Band.collection.aggregate([ { '$lookup' => { from: 'tours', localField: '_id', foreignField: 'band_id', as: 'tours', } }, { '$lookup' => { from: 'awards', localField: '_id', foreignField: 'band_id', as: 'awards', } }, { '$match' => { 'tours.year' => {'$gte' => 2000}, 'awards._id' => {'$exists' => true}, } }, {'$project' => {_id: 1}}, ]) bands = Band.find(band_ids.to_a)
[ {"_id": "...", "name": "Deftones" }, {"_id": "...", "name": "Tool"}, ... ]
Tip
上記の例では、出力ドキュメントの _idフィールドのみがプロジェクションされます。 次に、プロジェクションされた結果を使用してドキュメントが検索され、Mongoid::Document モデル インスタンスとして返されます。 このオプションの手順は、集計パイプライン を実行するために必要ではありません。
詳細情報
集計演算子の完全なリストを表示するには、「 集計演算子 」を参照してください。
集計パイプラインの組み立てと例については、「集計パイプライン 」を参照してください。
API ドキュメント
このガイドで説明されているメソッドの詳細については、次の API ドキュメントを参照してください。