Menu Docs
Página inicial do Docs
/ / /
Laravel MongoDB
/

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

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:

  • Adicionar a dependência do construtor de agregação

  • Criar um pipeline de agregação

  • Criar uma fábrica de operadores personalizados

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.

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",

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

Para saber mais sobre classes de construtor, consulte o Github repositório mongodb/mongodb-php-builder Github.

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.

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'))],
]);

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ções Query::query() e Query::eq()

  • Corresponde a documentos que contêm um campo name com um valor de "Eliud Nkosana" usando as funções Query::query() e Query::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.

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 construtor Expression

  • Referencia os valores do documento no campo occupation chamando a função Expression::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 .

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"
}
}
}
]

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" }
]

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 campo birthday .

  • Agrupe os documentos pelo valor do campo occupation e calcule o valor médio de birth_year para cada grupo usando a função Accumulator::avg() . Atribua o resultado do cálculo ao campo birth_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 campo birth_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.

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 campo birthday e atribuí-lo ao campo birth_year

  • project(), que inclui somente os campos name e birth_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
}
]

Voltar

Operações de Escrita