Construtor de agregações
Nesta página
- Visão geral
- Adicionar a dependência do construtor de agregação
- Criar um pipeline de agregação
- Documentos de amostra
- Exemplo de estágio de correspondência
- Exemplo de estágio de grupo
- Exemplo de estágio de classificação
- Exemplo de estágio do projeto
- Exemplo de pipeline de agregação
- Criar uma fábrica de operadores personalizados
Visão geral
Neste guia, você pode aprender como executar agregações e construir pipelines usando o construtor de agregação Laravel. O construtor de agregação permite que você use uma sintaxe segura de tipo para construir um pipeline de agregação MongoDB .
Uma aggregation pipeline é uma pipeline de processamento de dados que executa sequencialmente transformações e cálculos em dados do banco de MongoDB database e, em seguida, gera os resultados como um novo documento ou conjunto de documentos.
Um pipeline de agregação é composto de estágios de agregação. Os estágios de agregação usam operadores para processar dados de entrada e produzir dados que o próximo estágio usa como entrada.
O construtor de agregação Laravel MongoDB permite criar estágios de agregação e pipelines de agregação. As seções a seguir mostram exemplos de como usar o construtor de agregação para criar os estágios de um pipeline de agregação:
Dica
O recurso de construtor de agregação está disponível somente nas versões 4.3 e posteriores do Laravel MongoDB . Para saber mais sobre como executar agregações sem usar o construtor de agregação , consulteAgregações no guia Construtor de Query.
Adicionar a dependência do construtor de agregação
O construtor de aggregation faz parte do pacote MongoDB/builder. Você deve adicionar este pacote como uma dependência ao seu projeto para usá-lo. Execute o seguinte comando para adicionar a dependência do construtor de agregação ao seu aplicativo:
composer require mongodb/builder:^0.2
Quando a instalação for concluída, verifique se o arquivo composer.json
inclui a seguinte linha no objeto require
:
"mongodb/builder": "^0.2",
Criar um pipeline de agregação
Para iniciar um pipeline de agregação, chame o método Model::aggregate()
. Em seguida, encadeie os métodos do estágio de agregação na sequência em que deseja que eles executem.
O construtor de agregação inclui os seguintes namespaces que você pode importar para construir estágios de agregação:
MongoDB\Builder\Accumulator
MongoDB\Builder\Expression
MongoDB\Builder\Query
MongoDB\Builder\Type
Dica
Esta seção apresenta os seguintes exemplos, que mostram como usar estágios de agregação comuns e combinar estágios para criar um pipeline de agregação:
Para saber mais sobre os operadores de agregação MongoDB , consulte Estágios de agregação no manual do servidor MongoDB.
Documentos de amostra
Os exemplos seguintes executam pipelines de agregação em uma coleção representada pelo modelo User
. Você pode adicionar os dados de amostra executando o seguinte método 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'))], ]);
Exemplo de estágio de correspondência
Você pode encadear o método match()
ao seu pipeline de agregação para especificar um filtro de query. Se você omitir este estágio, o método aggregate()
produzirá todos os documentos na collection do modelo para o estágio seguinte.
Esse estágio de agregação geralmente é colocado em primeiro lugar para recuperar os dados usando índices disponíveis e reduzir a quantidade de dados do processo dos estágios subsequentes.
Dica
Se você omitir o método match()
, o pipeline de agregação corresponderá a todos os documentos da coleção que correspondem ao modelo antes de outros estágios de agregação.
Este exemplo constrói um filtro de query para um estágio de agregação de correspondência usando o construtor MongoDB\Builder\Query
. O estágio de correspondência inclui os seguintes critérios:
Retorna resultados que correspondem a qualquer um dos filtros de query usando a função
Query::or()
Corresponde a documentos que contêm um campo
occupation
com um valor de"designer"
usando as funçõesQuery::query()
eQuery::eq()
Corresponde a documentos que contêm um campo
name
com um valor de"Eliud Nkosana"
usando as funçõesQuery::query()
eQuery::eq()
Clique no botão VIEW OUTPUT para ver os documentos retornados executando o código:
$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" } } } ]
Dica
A função Query::or()
corresponde ao operador de query $or
do MongoDB. Para saber mais sobre esse operador, consulte $or no manual do servidor MongoDB.
Exemplo de estágio de grupo
Você pode encadear o método group()
ao seu aggregation pipeline para modificar a estrutura dos dados realizando cálculos e agrupando-os por valores de campo comuns.
Esse estágio de agregação geralmente é colocado imediatamente após um estágio de correspondência para reduzir o processo dos estágios subsequentes dos dados.
Este exemplo utiliza o construtor MongoDB\Builder\Expression
para definir as chaves de grupo em um estágio de agregação de grupo . O estágio de grupo especifica o seguinte comportamento de agrupamento:
Define o valor da chave de grupo, representada pelo campo
_id
, para o valor de campo definido pelo construtorExpression
Referencia os valores do documento no campo
occupation
chamando a funçãoExpression::fieldPath()
Clique no botão VIEW OUTPUT para ver os documentos retornados executando o código:
$pipeline = User::aggregate() ->group(_id: Expression::fieldPath('occupation')); $result = $pipeline->get();
[ { "_id": "engineer" }, { "_id": "designer" } ]
Dica
Este estágio de exemplo executa uma tarefa semelhante à do método construtor de query distinct()
. Para saber mais sobre o método distinct()
, consulte o exemplo de uso Recuperar valores de campo distintos .
Exemplo de estágio de classificação
Você pode encadear o método sort()
ao aggregation pipeline para especificar a ordem de saída dos documentos.
Você pode adicionar esse estágio de agregação em qualquer lugar do pipeline. Muitas vezes, é colocado após o estágio de grupos, pois pode depender dos dados agrupados. Recomendamos colocar o estágio de classificação o mais tarde possível no pipeline para limitar os dados que ele processa.
Para especificar uma classificação, defina o valor do campo como Sort::Asc
enum para uma classificação ascendente ou Sort::Desc
enum para uma classificação descendente.
Este exemplo mostra um estágio de pipeline de agregação sort()
que classifica os documentos pelo campo name
a Sort::Desc
, correspondendo à ordem alfabética inversa. Clique no botão VIEW OUTPUT para ver os documentos retornados executando o código:
$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" } } } ]
Exemplo de estágio do projeto
Você pode encadear o método project()
ao seu aggregation pipeline para especificar quais campos dos documentos devem ser exibidos por esse estágio.
Para especificar campos a serem incluídos, passe o nome de um campo e um valor verdadeiro, como 1
ou true
. Todos os outros campos são omitidos da saída.
Como alternativa, para especificar campos a serem excluídos, passe cada nome de campo e um valor falso, como 0
ou false
. Todos os outros campos estão incluídos no resultado.
Dica
Quando você especifica campos a serem incluídos, o campo _id
é incluído por padrão. Para excluir o campo _id
, exclua-o explicitamente no estágio de projeção.
Este exemplo mostra como usar o estágio de agregação do método project()
para incluir somente o campo name
e excluir todos os outros campos da saída. Clique no botão VIEW OUTPUT para ver os dados retornados executando o código:
$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" } ]
Exemplo de pipeline de agregação
Esse exemplo de pipeline de agregação encadeia vários estágios. Cada estágio é executado na saída recuperada de cada estágio anterior. Neste exemplo, os estágios executam as seguintes operações sequencialmente:
Adicione o campo
birth_year
aos documentos e defina o valor para o ano extraído do campobirthday
.Agrupe os documentos pelo valor do campo
occupation
e calcule o valor médio debirth_year
para cada grupo usando a funçãoAccumulator::avg()
. Atribua o resultado do cálculo ao campobirth_year_avg
.Classifique os documentos pelo campo chave de grupo em ordem crescente.
Crie o campo
profession
a partir do valor do campo chave de grupo, inclua o campobirth_year_avg
e omita o campo_id
.
Clique no botão VIEW OUTPUT para ver os dados retornados executando o código:
$pipeline = User::aggregate() ->addFields( birth_year: Expression::year( Expression::dateFieldPath('birthday'), ), ) ->group( _id: Expression::fieldPath('occupation'), birth_year_avg: Accumulator::avg(Expression::numberFieldPath('birth_year')), ) ->sort(_id: Sort::Asc) ->project(profession: Expression::fieldPath('_id'), birth_year_avg: 1, _id: 0);
[ { "birth_year_avg": 1991.5, "profession": "designer" }, { "birth_year_avg": 1995.5, "profession": "engineer" } ]
Observação
Como esse pipeline omite o estágio match()
, a entrada para o estágio inicial consiste em todos os documentos da collection.
Criar uma fábrica de operadores personalizados
Ao usar o construtor de agregação para criar um pipeline de agregação, você pode definir operações ou estágios em uma fábrica de operadores personalizada. Uma fábrica de operadores personalizados é uma função que retorna expressões ou estágios de uma aggregation pipeline. Você pode criar essas funções para melhorar a legibilidade e a reutilização do código.
Este exemplo mostra como criar e usar uma fábrica de operadores personalizados que retorna expressões que extraem o ano de um campo de data especificado.
A função a seguir aceita o nome de um campo que contém uma data e retorna uma expressão que extrai o ano da data:
public function yearFromField(string $dateFieldName): YearOperator { return Expression::year( Expression::dateFieldPath($dateFieldName), ); }
O exemplo de aggregation pipeline inclui os seguintes estágios:
addFields()
, que chama a função de fábrica do operador personalizado para extrair o ano do campobirthday
e atribuí-lo ao campobirth_year
project()
, que inclui somente os camposname
ebirth_year
em sua saída
Clique no botão VIEW OUTPUT para ver os dados retornados executando o código:
$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 } ]