Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
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.

Un pipeline de agregación es un pipeline de procesamiento de datos que realiza transformaciones y cálculos secuenciales en datos de la base de datos de MongoDB y luego entrega los resultados como un documento nuevo o un 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 MongoDB para Laravel te permite crear etapas de agregación y pipeline de agregación. Las siguientes secciones muestran ejemplos de cómo utilizar el constructor de agregaciones para crear las etapas de un pipeline de agregación:

  • Añade la dependencia del constructor de agregación

  • Crea una pipeline de agregación

  • Crear una fábrica de operadores personalizada

Tip

La funcionalidad builder de agregación está disponible solo en las versiones 4.3 y posteriores de Laravel MongoDB. Para obtener más información sobre la ejecución de agregaciones sin usar el constructor de agregaciones, consulta Agregaciones en la guía del Generador de query.

El generador de agregaciones forma parte del paquete mongodb/builder. Debe agregar este paquete como dependencia a su proyecto para usarlo. Ejecute el siguiente comando para agregar la dependencia del generador de agregaciones a su aplicación:

composer require mongodb/builder:^0.2

Cuando finalice la instalación, verifique que composer.json el archivo incluye la siguiente línea en el objeto require:

"mongodb/builder": "^0.2",

Para iniciar un pipeline de agregación, llama al método Model::aggregate(). Luego, encadena los métodos de la etapa de agregación en la secuencia en la que deseas que se ejecuten.

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

Tip

Para obtener más información sobre las clases builder, consulta el repositorio de GitHub mongodb/mongodb-php-builder.

En esta sección se presentan los siguientes ejemplos, que muestran cómo utilizar etapas de agregación comunes y combinar etapas para crear una canalización de agregación:

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

Puedes encadenar el método match() a tu pipeline de agregación para especificar un filtro de query. Si omites esta etapa, el método aggregate() genera todos los documentos en 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 query para una etapa de agregación match utilizando el constructor MongoDB\Builder\Query. 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" utilizando las funciones Query::query() y Query::eq()

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

Haga clic en el VIEW OUTPUT botón para ver los documentos devueltos al ejecutar 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 función Query::or() corresponde al operador del query de MongoDB $or. Para obtener más información sobre este operador, consulta $or en el manual del Servidor.

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

Esta etapa de agregación a menudo se coloca inmediatamente después de una etapa de coincidencia para reducir los datos que las etapas posteriores procesan.

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, al valor de campo definido por el generador Expression

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

Haz 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.

Puedes encadenar el método sort() a tu pipeline de agregación para especificar el orden de salida de los documentos.

Puedes agregar esta etapa de agregación en cualquier lugar del pipeline. A menudo se coloca después de la etapa de grupo ya que puede depender de los datos agrupados. Recomendamos colocar la etapa de ordenamiento lo más tarde posible en el pipeline para limitar los datos que procesa.

Para especificar un ordenamiento, establece el valor del campo en el enumerado Sort::Asc para un orden ascendente o en el enumerado Sort::Desc para un orden 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, pasa el nombre de un campo y un valor verdadero, como 1 o true. Todos los demás campos se omiten de 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" }
]

Este ejemplo de canalización de agregación encadena múltiples etapas. Cada etapa se ejecuta con el resultado recuperado de cada etapa anterior. En este ejemplo, las etapas realizan las siguientes operaciones de manera secuencial:

  • Agrega el campo birth_year a los documentos y establece el valor al año extraído del campo birthday.

  • Agrupa los documentos por el valor del campo occupation y calcula el valor promedio de birth_year para cada grupo usando la función Accumulator::avg(). Asigna el resultado del cálculo al campo birth_year_avg.

  • Ordene los documentos por el campo clave de grupo en orden ascendente.

  • Cree el campo profession a partir del valor del campo de clave de grupo, incluya el campo birth_year_avg y omita el campo _id.

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

Nota

Dado que esta pipeline omite la etapa match(), la entrada para la etapa inicial consiste en todos los documentos de la colección.

Al usar el constructor de agregaciones para crear un pipeline 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 un pipeline de agregación. Puede crear estas funciones para mejorar la legibilidad y reutilización del código.

Este ejemplo muestra cómo crear y utilizar una fábrica de operadores personalizados que devuelvan 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 pipeline de agregación de ejemplo 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

Haz 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