Menu Docs
Página inicial do Docs
/ / /
Mongoid
/

Pipeline de agregação

Nesta página

  • Uso básico
  • Consultando em várias coleções
  • Builder DSL
  • grupo, grupo
  • projeto, projeto
  • Unwind

O Mongoid expõeo agregação pipeline do MongoDB, que é usado para construir fluxos de operações que processam e retornam resultados. O pipeline de agregação é um superconjunto da funcionalidade deestrutura de mapa/redução de obsoleta.

O agregação pipeline pode ser usado para queries envolvendo várias associações referenciadas ao mesmo tempo:

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

Para recuperar bandas que fizeram turnês desde 2000 e têm pelo menos um prêmios, pode-se fazer o seguinte:

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)

Observe que o agregação pipeline, uma vez que é implementado pelo driver Ruby para MongoDB e não Mongoid, retorna objetos brutos BSON::Document em vez de instâncias de modelo Mongoid::Document . O exemplo acima projeta somente o campo _id que é então utilizado para carregar modelos completos. Uma alternativa é não realizar tal projeção e trabalhar com campos brutos, o que eliminaria a necessidade de enviar a lista de IDs de documento para o Mongoid na segunda query (que pode ser grande).

O Mongoid fornece suporte limitado para a construção do próprio pipeline de agregação usando um DSL de alto nível. Os seguintes operadores de pipeline de agregação são compatíveis:

  • $group

  • $project

  • $unwind

Para construir um pipeline, chame os métodos de pipeline de agregação correspondentes em uma instância do Criteria . As operações de pipeline de agregação são adicionadas ao pipeline atributo da Criteria instância . Para executar o pipeline, passe o pipeline valor do atributo Collection#aggragegate .

Por exemplo, dado os modelos a seguir:

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

Podemos descobrir quais estados um participante visitou:

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

O método group adiciona um estágio de pipeline de agregação $group.

As expressões de campo suportam a sintaxe do operador de símbolo Mongoid :

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

Como alternativa, a sintaxe padrão do pipeline de agregação do MongoDB pode ser usada:

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

O método project adiciona um estágio de pipeline de agregação do projeto $.

O argumento deve ser um Hash especificando a projeção:

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

O método unwind adiciona um estágio de pipeline de agregação $unwind.

O argumento pode ser um nome de campo , especificável como um símbolo ou uma string, ou um Hash ou uma instância 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"}}]

Voltar

Pesquisa de texto