Docs Menu
Docs Home
/ /

Creador de agregaciones

En esta guía, aprenderá a realizar agregaciones y construir pipelines con el generador de agregaciones de Laravel Integration. Este generador le permite usar una sintaxis con seguridad de tipos para construir un pipeline de agregación de MongoDB.

Una canalización de agregación es una canalización de procesamiento de datos que realiza de forma secuencial transformaciones y cálculos sobre datos de la base de datos MongoDB y luego genera los resultados como un nuevo documento o conjunto de documentos.

Una canalización de agregación se compone de etapas de agregación. Estas etapas utilizan operadores para procesar los datos de entrada y generar datos que la siguiente etapa utiliza como entrada.

El generador de agregaciones de Laravel MongoDB permite crear etapas y pipelines de agregación. Las siguientes secciones muestran ejemplos de cómo usar el generador de agregaciones para crear las etapas de un pipeline de agregación:

  • Crear etapas de agregación

  • Construir pipelines de agregación

  • Crear una fábrica de operadores personalizada

Tip

El generador de agregaciones solo está disponible en las versiones 4.3 y posteriores de Laravel MongoDB. Para obtener más información sobre cómo ejecutar agregaciones sin usar el generador de agregaciones, consulte Agregaciones en la guía del generador de consultas.

Para iniciar una canalización de agregación, llame al Model::aggregate() Método. Luego, encadene los métodos de la etapa de agregación y especifique los parámetros necesarios para la etapa. Por ejemplo, puede llamar al método del operador sort() para crear una etapa $sort.

El generador de agregación incluye los siguientes espacios de nombres que puede importar para crear etapas de agregación:

  • MongoDB\Builder\Accumulator

  • MongoDB\Builder\Expression

  • MongoDB\Builder\Query

  • MongoDB\Builder\Type

En esta sección se presentan los siguientes ejemplos que muestran cómo utilizar etapas de agregación comunes:

Para obtener más información sobre los operadores de agregación de MongoDB, consulte Etapas de agregación en el manual del servidor.

Los siguientes ejemplos ejecutan canalizaciones de agregación en una colección representada por el modelo User. Puede agregar los datos de muestra ejecutando el siguiente 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'))],
]);

Puede encadenar el método match() a su canalización de agregación para especificar un filtro de consulta. Si omite esta etapa, el método aggregate() genera todos los documentos de la colección del modelo para la siguiente etapa.

Esta etapa de agregación a menudo se coloca primero para recuperar los datos utilizando los índices disponibles y reducir la cantidad de datos que procesan las etapas posteriores.

Tip

Si omite el método match(), la canalización de agregación coincide con todos los documentos de la colección que corresponden al modelo antes de otras etapas de agregación.

Este ejemplo construye un filtro de consulta para una etapa de agregación de coincidencias mediante el MongoDB\Builder\Query constructor. La etapa de coincidencia incluye los siguientes criterios:

  • Devuelve resultados que coinciden con cualquiera de los filtros de consulta mediante la función Query::or()

  • Coincide con documentos que contienen un campo occupation con un valor de "designer" mediante las funciones Query::query() y Query::eq()

  • Coincide con documentos que contienen un campo name con un valor de "Eliud Nkosana" mediante las funciones Query::query() y Query::eq()

Haga clic en el VIEW OUTPUT Botón para ver los documentos devueltos ejecutando el 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"
}
}
}
]

Tip

La Query::or() función corresponde al $or operador de consulta de MongoDB. Para obtener más información sobre este operador, consulte $or en el manual del servidor.

Puede encadenar el método group() a su canal de agregación para modificar la estructura de los datos realizando cálculos y agrupándolos por valores de campo comunes.

Esta etapa de agregación a menudo se coloca inmediatamente después de una etapa de coincidencia para reducir el procesamiento de datos en las etapas posteriores.

Este ejemplo utiliza el MongoDB\Builder\Expression constructor para definir las claves de grupo en una etapa de agregación de grupos. La etapa de grupo especifica el siguiente comportamiento de agrupación:

  • Establece el valor de la clave de grupo, representada por el campo _id, en el valor del campo definido por el generador Expression

  • Hace referencia a los valores del documento en el campo occupation llamando a la función Expression::fieldPath()

Haga clic en el botón VIEW OUTPUT para ver los documentos devueltos al ejecutar el código:

$pipeline = User::aggregate()
->group(_id: Expression::fieldPath('occupation'));
$result = $pipeline->get();
[
{ "_id": "engineer" },
{ "_id": "designer" }
]

Tip

Esta etapa de ejemplo realiza una tarea similar a la del distinct() método del generador de consultas. Para obtener más información sobre el distinct() método, consulte el ejemplo de uso de Recuperar valores de campo distintos.

Puede encadenar el método sort() a su canal de agregación para especificar el orden de salida de los documentos.

Puede agregar esta etapa de agregación en cualquier punto del pipeline. Suele colocarse después de la etapa de agrupación, ya que depende de los datos agrupados. Recomendamos colocar la etapa de ordenación lo más tarde posible en el pipeline para limitar los datos que procesa.

Para especificar un ordenamiento, establezca el valor del campo en la enumeración Sort::Asc para un ordenamiento ascendente o en la enumeración Sort::Desc para un ordenamiento descendente.

Este ejemplo muestra una etapa de canalización de agregación sort() que ordena los documentos desde el campo name hasta el Sort::Desc, lo que corresponde al orden alfabético inverso. Haga clic en el botón VIEW OUTPUT para ver los documentos devueltos al ejecutar el 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"
}
}
}
]

Puedes encadenar el método project() a tu pipeline de agregación para especificar los campos de los documentos que se mostrarán en esta etapa.

Para especificar los campos a incluir, pase el nombre de un campo y un valor verdadero, como 1 o true. Los demás campos se omiten en la salida.

Como alternativa, para especificar los campos que se excluirán, pase el nombre de cada campo y un valor falso, como 0 o false. Todos los demás campos se incluyen en la salida.

Tip

Al especificar los campos que se incluirán, el campo _id se incluye de forma predeterminada. Para excluir el campo _id, exclúyalo explícitamente en la etapa de proyección.

Este ejemplo muestra cómo usar la etapa de agregación del método project() para incluir solo el campo name y excluir todos los demás campos de la salida. Haga clic en el botón VIEW OUTPUT para ver los datos devueltos al ejecutar el 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" }
]

Para crear una canalización de agregación, llame al método Model::aggregate() y, a continuación, encadene las etapas de agregación en la secuencia deseada. Los ejemplos de esta sección están adaptados del manual del servidor. Cada ejemplo proporciona un enlace a los datos de muestra que puede insertar en su base de datos para probar la operación de agregación.

En esta sección se presentan los siguientes ejemplos, que muestran cómo utilizar etapas de agregación comunes:

Este ejemplo utiliza los datos de muestra proporcionados en la sección Calcular recuento, suma y promedio de la referencia de la $group etapa en el manual del servidor.

El siguiente ejemplo de código calcula el importe total de ventas, la cantidad promedio de ventas y el recuento de ventas para cada día del año 2014. Para ello, utiliza una canalización de agregación que consta de las siguientes etapas:

  1. Etapa $match para filtrar documentos que contienen un date campo en el que el año es 2014

  2. Etapa de grupo para agrupar los documentos por fecha y calcular el monto total de ventas, la cantidad promedio de ventas y el recuento de ventas para cada grupo

  3. Etapa $sort para ordenar los resultados por el monto total de venta para cada grupo en orden descendente

Haga clic en el botón VIEW OUTPUT para ver los datos devueltos al ejecutar el código:

$pipeline = Sale::aggregate()
->match(
date: [
Query::gte(new UTCDateTime(new DateTimeImmutable('2014-01-01'))),
Query::lt(new UTCDateTime(new DateTimeImmutable('2015-01-01'))),
],
)
->group(
_id: Expression::dateToString(Expression::dateFieldPath('date'), '%Y-%m-%d'),
totalSaleAmount: Accumulator::sum(
Expression::multiply(
Expression::numberFieldPath('price'),
Expression::numberFieldPath('quantity'),
),
),
averageQuantity: Accumulator::avg(
Expression::numberFieldPath('quantity'),
),
count: Accumulator::sum(1),
)
->sort(
totalSaleAmount: Sort::Desc,
);
[
{ "_id": "2014-04-04", "totalSaleAmount": { "$numberDecimal": "200" }, "averageQuantity": 15, "count": 2 },
{ "_id": "2014-03-15", "totalSaleAmount": { "$numberDecimal": "50" }, "averageQuantity": 10, "count": 1 },
{ "_id": "2014-03-01", "totalSaleAmount": { "$numberDecimal": "40" }, "averageQuantity": 1.5, "count": 2 }
]

Este ejemplo utiliza los datos de muestra proporcionados en la sección Unwind Embedded Arrays de la $unwind referencia de la etapa en el manual del servidor.

El siguiente ejemplo de código agrupa los artículos vendidos por sus etiquetas y calcula el importe total de ventas para cada etiqueta. Para ello, utiliza una canalización de agregación que consta de las siguientes etapas:

  1. Etapa$unwind para generar un documento separado para cada elemento en la items matriz

  2. Etapa$unwind para generar un documento separado para cada elemento en las items.tags matrices

  3. Etapa de grupo para agrupar los documentos por valor de etiqueta y calcular el monto total de ventas de los artículos que tienen cada etiqueta

Haga clic en el botón VIEW OUTPUT para ver los datos devueltos al ejecutar el código:

$pipeline = Sale::aggregate()
->unwind(Expression::arrayFieldPath('items'))
->unwind(Expression::arrayFieldPath('items.tags'))
->group(
_id: Expression::fieldPath('items.tags'),
totalSalesAmount: Accumulator::sum(
Expression::multiply(
Expression::numberFieldPath('items.price'),
Expression::numberFieldPath('items.quantity'),
),
),
);
[
{ "_id": "school", "totalSalesAmount": { "$numberDecimal": "104.85" } },
{ "_id": "electronics", "totalSalesAmount": { "$numberDecimal": "800.00" } },
{ "_id": "writing", "totalSalesAmount": { "$numberDecimal": "60.00" } },
{ "_id": "office", "totalSalesAmount": { "$numberDecimal": "1019.60" } },
{ "_id": "stationary", "totalSalesAmount": { "$numberDecimal": "264.45" } }
]

Este ejemplo utiliza los datos de muestra proporcionados en la sección Realizar una unión de igualdad única con $lookup de la referencia de la $lookup etapa en el manual del servidor.

El siguiente ejemplo de código une los documentos de la colección orders con los documentos de la colección inventory usando el campo item de la colección orders y el campo sku de la colección inventory.

Para ello, el ejemplo utiliza una canalización de agregación que contiene una etapa $lookup que especifica la colección de la que se recuperarán los datos y los nombres de los campos locales y externos.

Haga clic en el botón VIEW OUTPUT para ver los datos devueltos al ejecutar el código:

$pipeline = Order::aggregate()
->lookup(
from: 'inventory',
localField: 'item',
foreignField: 'sku',
as: 'inventory_docs',
);
[
{ "_id": 1, "item": "almonds", "price": 12, "quantity": 2, "inventory_docs": [
{ "_id": 1, "sku": "almonds", "description": "product 1", "instock": 120 }
] },
{ "_id": 2, "item": "pecans", "price": 20, "quantity": 1, "inventory_docs": [
{ "_id": 4, "sku": "pecans", "description": "product 4", "instock": 70 }
] },
{ "_id": 3, "inventory_docs": [
{ "_id": 5, "sku": null, "description": "Incomplete" },
{ "_id": 6 }
] }
]

Al usar el generador de agregaciones para crear una canalización de agregación, puede definir operaciones o etapas en una fábrica de operadores personalizada. Una fábrica de operadores personalizada es una función que devuelve expresiones o etapas de una canalización de agregación. Puede crear estas funciones para mejorar la legibilidad y la reutilización del código.

Este ejemplo muestra cómo crear y utilizar una fábrica de operadores personalizada que devuelve expresiones que extraen el año de un campo de fecha especificado.

La siguiente función acepta el nombre de un campo que contiene una fecha y devuelve una expresión que extrae el año de la fecha:

public function yearFromField(string $dateFieldName): YearOperator
{
return Expression::year(
Expression::dateFieldPath($dateFieldName),
);
}

El ejemplo de canalización de agregación incluye las siguientes etapas:

  • addFields(), que llama a la función de la fábrica de operadores personalizados para extraer el año del campo birthday y asignarlo al campo birth_year

  • project(), que incluye solo los campos name y birth_year en su salida

Haga clic en el botón VIEW OUTPUT para ver los datos devueltos al ejecutar el 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
}
]

Volver

Borrar

En esta página