Docs Menu
Docs Home
/ / /
Mongoid
/

Aggregation Pipeline

項目一覧

  • 基本的な用途
  • 複数のコレクションにわたるクエリ
  • ビルダ DSL
  • グループ
  • プロジェクト
  • unwind

Mongoid は、処理して結果を返す操作のフローを構築するために使用される MongoDB の 集計パイプラインを公開します。 集計パイプラインは、非推奨の map/reduce フレームワーク機能のスーパーセットです。

集計パイプラインは、同時に参照される複数の関連付けを含むクエリに使用できます。

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)

集計パイプラインは、Mongoid ではなく MongoDB の Ruby ドライバーによって実装されているため、 Mongoid::Documentモデル インスタンスではなく、未加工の BSON::Documentオブジェクトを返します。 上記の例では、 _idフィールドのみがプロジェクションされており、このフィールドは完全なモデルを読み込むために使用されます。 代替策として、そのようなプロジェクションを実行せず、未加工のフィールドを操作することにより、2 番目のクエリ(

Mongoid は、高レベルの DSL を使用して集計パイプライン自体を構築するための限定的なサポートを提供します。 次の集計パイプライン演算子がサポートされています。

  • $group

  • $project

  • $unwind

パイプラインを構築するには、 Criteriaインスタンスで対応する集計パイプライン メソッドを呼び出します。 集計パイプライン操作は、 Criteriaインスタンスのpipeline属性に追加されます。 パイプラインを実行するには、 pipeline属性値をCollection#aggragegateメソッドに渡します。

次のモデルを例にしましょう。

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

参加者が訪問した州を見つけることができます。

criteria = Tour.where('participants.name' => 'Serenity',).
unwind(:states).
group(_id: 'states', :states.add_to_set => '$states').
project(_id: 0, states: 1)
pp criteria.pipeline
# => [{"$match"=>{"participants.name"=>"Serenity"}},
# {"$unwind"=>"$states"},
# {"$group"=>{"_id"=>"states", "states"=>{"$addToSet"=>"$states"}}},
# {"$project"=>{"_id"=>0, "states"=>1}}]
Tour.collection.aggregate(criteria.pipeline).to_a

groupメソッドは$group 集計パイプライン ステージを追加します。

フィールド式は Mongoid シンボル演算子構文をサポートします。

criteria = Tour.all.group(_id: 'states', :states.add_to_set => '$states')
criteria.pipeline
# => [{"$group"=>{"_id"=>"states", "states"=>{"$addToSet"=>"$states"}}}]

あるいは、標準の MongoDB 集計パイプライン構文を使用することもできます。

criteria = Tour.all.group(_id: 'states', states: {'$addToSet' => '$states'})

projectメソッドは$project 集計パイプライン ステージを追加します。

引数は、プロジェクションを指定する ハッシュ である必要があります。

criteria = Tour.all.project(_id: 0, states: 1)
criteria.pipeline
# => [{"$project"=>{"_id"=>0, "states"=>1}}]

unwindメソッドは$unwind 集計パイプライン ステージを追加します。

引数は、シンボルまたは string として指定可能なフィールド名、またはハッシュまたはBSON::Documentインスタンスにすることができます。

criteria = Tour.all.unwind(:states)
criteria = Tour.all.unwind('states')
criteria.pipeline
# => [{"$unwind"=>"$states"}]
criteria = Tour.all.unwind(path: '$states')
criteria.pipeline
# => [{"$unwind"=>{:path=>"$states"}}]

戻る

テキスト検索