Docs Menu
Docs Home
/ /
/ / /

Constructores de agregados

En esta guía, podrá aprender a utilizar el Clase de agregados que proporciona métodos de fábrica estáticos que crean etapas de canalización de agregación en el controlador MongoDB Kotlin.

Para una introducción más completa a la agregación, consulte nuestro Guía de agregación.

Los ejemplos de esta página suponen importaciones para métodos de las siguientes clases:

  • Aggregates

  • Filters

  • Projections

  • Sorts

  • Accumulators

import com.mongodb.client.model.Aggregates
import com.mongodb.client.model.Filters
import com.mongodb.client.model.Projections
import com.mongodb.client.model.Sorts
import com.mongodb.client.model.Accumulators

Utilice estos métodos para construir etapas de canalización y especificarlas en su agregación como una lista:

val matchStage = Aggregates.match(Filters.eq("someField", "someCriteria"))
val sortByCountStage = Aggregates.sortByCount("\$someField")
val results = collection.aggregate(
listOf(matchStage, sortByCountStage)).toList()

Muchos Aggregation ejemplos de esta guía utilizan el conjunto de datos Atlas sample_mflix.movies. Los documentos de esta colección se modelan mediante la siguiente Movie clase de datos para su uso con el controlador Kotlin:

data class Movie(
val title: String,
val year: Int,
val genres: List<String>,
val rated: String,
val plot: String,
val runtime: Int,
val imdb: IMDB,
val fullplot: String? = "No full plot",
){
data class IMDB(
val rating: Double
)
}

Tip

Métodos de construcción y propiedades de la clase de datos

Puedes usar los métodos de las clases de constructor directamente con las propiedades de las clases de datos añadiendo la dependencia opcional de extensiones del controlador Kotlin a tu aplicación. Para obtener más información y ver ejemplos, consulta la guía "Usar constructores con clases de datos".

Utilice el match() método para crear una etapa de canalización $match que compare los documentos entrantes con el filtro de consulta especificado y filtre los documentos que no coinciden.

Tip

El filtro puede ser una instancia de cualquier clase que Bson implemente, pero es conveniente combinarlo con el uso de la clase Filtros.

El siguiente ejemplo crea una etapa de canalización que coincide con todos los documentos de la colección movies donde el campo title es igual a "The Shawshank Redemption":

Aggregates.match(Filters.eq(Movie::title.name, "The Shawshank Redemption"))

Utilice el método project() para crear una etapa de pipeline $project que proyecte los campos de documento especificados. La proyección de campos en agregación sigue las mismas reglas que la proyección de campos en las consultas.

Tip

Aunque la proyección puede ser una instancia de cualquier clase que Bson implemente, es conveniente combinarla con el uso de Proyecciones.

El siguiente ejemplo crea una etapa de canalización que incluye los campos title y plot pero excluye el campo _id:

Aggregates.project(
Projections.fields(
Projections.include(Movie::title.name, Movie::plot.name),
Projections.excludeId())
)

La etapa $project también puede proyectar campos calculados.

El siguiente ejemplo crea una etapa de canalización que proyecta el campo rated en un nuevo campo llamado rating, cambiando efectivamente el nombre del campo:

Aggregates.project(
Projections.fields(
Projections.computed("rating", "\$${Movie::rated.name}"),
Projections.excludeId()
)
)

Utilice el documents() método para crear una etapa de canalización $documents que devuelva documentos literales a partir de valores de entrada.

Importante

Si utiliza una etapa $documents en una canalización de agregación, debe ser la primera etapa de la canalización.

El siguiente ejemplo crea una etapa de canalización que crea documentos de muestra en la colección movies con un campo title:

Aggregates.documents(
listOf(
Document(Movie::title.name, "Steel Magnolias"),
Document(Movie::title.name, "Back to the Future"),
Document(Movie::title.name, "Jurassic Park")
)
)

Importante

Si utiliza el método documents() para proporcionar la entrada a una canalización de agregación, debe llamar al método aggregate() en una base de datos en lugar de en una colección.

val docsStage = database.aggregate<Document>( // ... )

Utilice el sample() método para crear una etapa de canalización $sample para seleccionar documentos aleatoriamente de la entrada.

El siguiente ejemplo crea una etapa de canalización que selecciona aleatoriamente 5 documentos de la colección movies:

Aggregates.sample(5)

Utilice el sort() método para crear una etapa de canalización $sort para ordenar según los criterios especificados.

Tip

Aunque los criterios de clasificación pueden ser una instancia de cualquier clase que Bson implemente, es conveniente combinarlos con el uso de clasificaciones.

El siguiente ejemplo crea una etapa de canalización que ordena en orden descendente según el valor del campo year y luego en orden ascendente según el valor del campo title:

Aggregates.sort(
Sorts.orderBy(
Sorts.descending(Movie::year.name),
Sorts.ascending(Movie::title.name)
)
)

Utiliza el método skip() para crear una etapa de pipeline de $skip para omitir la cantidad específica de documentos antes de pasar los documentos a la siguiente etapa.

El siguiente ejemplo crea una etapa de canalización que omite los primeros 5 documentos en la colección movies:

Aggregates.skip(5)

Utilice la etapa de canalización $limit para limitar la cantidad de documentos que pasan a la siguiente etapa.

El siguiente ejemplo crea una etapa de canalización que limita la cantidad de documentos devueltos desde la colección movies a 4:

Aggregates.limit(4)

Utiliza el método lookup() para crear una etapa en la pipeline $lookup y realizar combinaciones y subconsultas no correlacionadas entre dos colecciones.

El siguiente ejemplo crea una etapa de canalización que realiza una unión externa izquierda entre las colecciones movies y comments en la base de datos de muestra mflix:

  1. Une el campo _id de movies al campo movie_id en comments

  2. Muestra los resultados en el campo joined_comments

Aggregates.lookup(
"comments",
"_id",
"movie_id",
"joined_comments"
)

El siguiente ejemplo utiliza las colecciones ficticias orders y warehouses. Los datos se modelan utilizando las siguientes clases de datos de Kotlin:

data class Order(
@BsonId val id: Int,
val customerId: Int,
val item: String,
val ordered: Int
)
data class Inventory(
@BsonId val id: Int,
val stockItem: String,
val inStock: Int
)

El ejemplo crea una etapa de pipeline que une las dos colecciones por el elemento y verifica si la cantidad disponible en el campo inStock es suficiente para cumplir con la cantidad ordered:

val variables = listOf(
Variable("order_item", "\$item"),
Variable("order_qty", "\$ordered")
)
val pipeline = listOf(
Aggregates.match(
Filters.expr(
Document("\$and", listOf(
Document("\$eq", listOf("$\$order_item", "\$${Inventory::stockItem.name}")),
Document("\$gte", listOf("\$${Inventory::inStock.name}", "$\$order_qty"))
))
)
),
Aggregates.project(
Projections.fields(
Projections.exclude(Order::customerId.name, Inventory::stockItem.name),
Projections.excludeId()
)
)
)
val innerJoinLookup =
Aggregates.lookup("warehouses", variables, pipeline, "stockData")

Utilice el group() método para crear una etapa de canalización $group para agrupar documentos mediante una expresión específica y generar un documento para cada agrupación distinta.

Tip

El controlador incluye la clase Accumulators con métodos de fábrica estáticos para cada uno de los acumuladores compatibles.

El siguiente ejemplo crea una etapa de canalización que agrupa los documentos de la colección orders según el valor del campo customerId. Cada grupo acumula la suma y el promedio de los valores del campo ordered en los campos totalQuantity y averageQuantity:

Aggregates.group("\$${Order::customerId.name}",
Accumulators.sum("totalQuantity", "\$${Order::ordered.name}"),
Accumulators.avg("averageQuantity", "\$${Order::ordered.name}")
)

Obtenga más información sobre los operadores de acumuladores en la sección del manual del servidor sobre Acumuladores.

Los acumuladores pick-n son operadores de acumulación que devuelven los elementos superior e inferior según un orden específico. Utilice uno de los siguientes constructores para crear un operador de acumulación:

Tip

Solo puede realizar operaciones de agregación con estos acumuladores pick-n cuando ejecuta MongoDB v5.2 o posterior.

Conozca en qué etapas del flujo de trabajo de agregación puede usar operadores acumuladores en la sección del manual del servidor sobre Acumuladores.

Los ejemplos del acumulador pick-n utilizan documentos de la colección movies en la base de datos sample-mflix.

El minN() constructor crea el acumulador $minN que devuelve datos de los documentos que contienen los n valores más bajos de una agrupación.

Tip

Los $minN $bottomN acumuladores y pueden realizar tareas similares. Consulte la Comparación de los acumuladores $minN y $bottomN para conocer el uso recomendado de cada uno.

El siguiente ejemplo demuestra cómo utilizar el método minN() para devolver los tres valores imdb.rating más bajos para películas, agrupados por year:

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.minN(
"lowestThreeRatings",
"\$${Movie::imdb.name}.${Movie.IMDB::rating.name}",
3
)
)

Consulte la documentación de la API minN() para obtener más información.

El acumulador maxN() devuelve datos de los documentos que contienen los n valores más altos de una agrupación.

El siguiente ejemplo demuestra cómo utilizar el método maxN() para devolver los dos valores imdb.rating más altos para películas, agrupados por year:

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.maxN(
"highestTwoRatings",
"\$${Movie::imdb.name}.${Movie.IMDB::rating.name}",
2
)
)

Consulte la documentación de la API maxN() para obtener más información.

El acumulador firstN() devuelve datos de los primeros n documentos en cada agrupación para el orden de clasificación especificado.

Tip

Los $firstN $topN acumuladores y pueden realizar tareas similares. Consulte la Comparación de los acumuladores $firstN y $topN para conocer el uso recomendado de cada uno.

El siguiente ejemplo demuestra cómo utilizar el método firstN() para devolver los dos primeros valores de la película title, según el orden en que llegaron al escenario, agrupados por year:

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.firstN(
"firstTwoMovies",
"\$${Movie::title.name}",
2
)
)

Consulte la documentación de la API firstN() para obtener más información.

El acumulador lastN() devuelve datos de los últimos n documentos en cada agrupación para el orden de clasificación especificado.

El siguiente ejemplo demuestra cómo utilizar el método lastN() para mostrar los últimos tres valores de la película title, según el orden en que llegaron al escenario, agrupados por year:

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.lastN(
"lastThreeMovies",
"\$${Movie::title.name}",
3
)
)

Consulta la documentación de lastN() API para más información.

El acumulador top() devuelve datos del primer documento de un grupo según el orden de clasificación especificado.

El siguiente ejemplo demuestra cómo utilizar el método top() para devolver los valores title y imdb.rating de las películas mejor calificadas según imdb.rating, agrupadas por year.

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.top(
"topRatedMovie",
Sorts.descending("${Movie::imdb.name}.${Movie.IMDB::rating.name}"),
listOf("\$${Movie::title.name}", "\$${Movie::imdb.name}.${Movie.IMDB::rating.name}")
)
)

Consulte la documentación de la API top() para obtener más información.

El acumulador topN() devuelve datos de los documentos que contienen los valores n más altos para el campo especificado.

Tip

Los $firstN $topN acumuladores y pueden realizar tareas similares. Consulte la Comparación de los acumuladores $firstN y $topN para conocer el uso recomendado de cada uno.

El siguiente ejemplo demuestra cómo utilizar el método topN() para devolver los valores title y runtime de las tres películas más largas según los valores runtime, agrupados por year.

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.topN(
"longestThreeMovies",
Sorts.descending(Movie::runtime.name),
listOf("\$${Movie::title.name}", "\$${Movie::runtime.name}"),
3
)
)

Consulte la documentación de la API topN() para obtener más información.

El acumulador bottom() devuelve datos del último documento de un grupo según el orden de clasificación especificado.

El siguiente ejemplo demuestra cómo utilizar el método bottom() para devolver los valores title y runtime de la película más corta según el valor runtime, agrupados por year.

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.bottom(
"shortestMovies",
Sorts.descending(Movie::runtime.name),
listOf("\$${Movie::title.name}", "\$${Movie::runtime.name}")
)
)

Consulte la documentación de la API bottom() para obtener más información.

El acumulador bottomN() devuelve datos de los documentos que contienen los valores n más bajos para el campo especificado.

Tip

Los $minN $bottomN acumuladores y pueden realizar tareas similares. Consulte la Comparación de los acumuladores $minN y $bottomN para conocer el uso recomendado de cada uno.

El siguiente ejemplo demuestra cómo utilizar el método bottomN() para devolver los valores title y imdb.rating de las dos películas con la calificación más baja según el valor imdb.rating, agrupados por year:

Aggregates.group(
"\$${Movie::year.name}",
Accumulators.bottom(
"lowestRatedTwoMovies",
Sorts.descending("${Movie::imdb.name}.${Movie.IMDB::rating.name}"),
listOf("\$${Movie::title.name}", "\$${Movie::imdb.name}.${Movie.IMDB::rating.name}"),
)
)

Consulte la documentación de la API bottomN() para obtener más información.

Utilice el unwind() método para crear una etapa de canalización $unwind para deconstruir un campo de matriz a partir de documentos de entrada, creando un documento de salida para cada elemento de la matriz.

El siguiente ejemplo crea un documento para cada elemento de la matriz lowestRatedTwoMovies:

Aggregates.unwind("\$${"lowestRatedTwoMovies"}")

Para conservar documentos que tienen valores faltantes o null para el campo de matriz, o donde la matriz está vacía:

Aggregates.unwind(
"\$${"lowestRatedTwoMovies"}",
UnwindOptions().preserveNullAndEmptyArrays(true)
)

Para incluir el índice de la matriz (en este ejemplo, en un campo llamado "position"):

Aggregates.unwind(
"\$${"lowestRatedTwoMovies"}",
UnwindOptions().includeArrayIndex("position")
)

Utilice el out() método para crear una etapa de canalización $out que escriba todos los documentos en la colección especificada en la misma base de datos.

Importante

La etapa $out debe ser la última etapa de cualquier pipeline de agregación.

El siguiente ejemplo escribe los resultados de la canalización en la colección classic_movies:

Aggregates.out("classic_movies")

Utilice el merge() método para crear una etapa de canalización $merge que fusione todos los documentos en la colección especificada.

Importante

La etapa $merge debe ser la última etapa de cualquier pipeline de agregación.

El siguiente ejemplo fusiona la canalización en la colección nineties_movies utilizando las opciones predeterminadas:

Aggregates.merge("nineties_movies")

El siguiente ejemplo fusiona la canalización en la colección movie_ratings en la base de datos aggregation utilizando algunas opciones no predeterminadas que especifican reemplazar el documento si year y title coinciden; de lo contrario, insertar el documento:

Aggregates.merge(
MongoNamespace("aggregation", "movie_ratings"),
MergeOptions().uniqueIdentifier(listOf("year", "title"))
.whenMatched(MergeOptions.WhenMatched.REPLACE)
.whenNotMatched(MergeOptions.WhenNotMatched.INSERT)
)

Utilice el graphLookup() método para crear una etapa de canalización $graphLookup que realice una búsqueda recursiva en una colección específica para hacer coincidir un campo específico en un documento con un campo específico de otro documento.

El siguiente ejemplo utiliza la colección contacts. Los datos se modelan con la siguiente clase de datos de Kotlin:

data class Users(
val name: String,
val friends: List<String>?,
val hobbies: List<String>?
)

El ejemplo calcula el gráfico de informes para los usuarios de la colección contact, haciendo coincidir de forma recursiva el valor del campo friends con el campo name:

Aggregates.graphLookup(
"contacts",
"\$${Users::friends.name}", Users::friends.name, Users::name.name,
"socialNetwork"
)

Usando GraphLookupOptions, puede especificar la profundidad de recursión y el nombre del campo de profundidad, si lo desea. En este ejemplo, $graphLookup se recursivamente hasta dos veces y creará un campo llamado degrees con la información de profundidad de recursión para cada documento.

Aggregates.graphLookup(
"contacts",
"\$${Users::friends.name}", Users::friends.name, Users::name.name,
"socialNetwork",
GraphLookupOptions().maxDepth(2).depthField("degrees")
)

Usando GraphLookupOptions, puede especificar un filtro que los documentos deben cumplir para que MongoDB los incluya en su búsqueda. En este ejemplo, solo se incluirán los enlaces con "golf" en su campo hobbies:

Aggregates.graphLookup(
"contacts",
"\$${Users::friends.name}", Users::friends.name, Users::name.name, "socialNetwork",
GraphLookupOptions().maxDepth(1).restrictSearchWithMatch(
Filters.eq(Users::hobbies.name, "golf")
)
)

Utilice el sortByCount() método para crear una etapa de canalización $sortByCount que agrupe los documentos mediante una expresión determinada y luego ordene estos grupos por conteo en orden descendente.

Tip

La etapa $sortByCount es idéntica a una etapa $group con un acumulador $sum seguido de una etapa $sort.

[
{ "$group": { "_id": <expression to group on>, "count": { "$sum": 1 } } },
{ "$sort": { "count": -1 } }
]

El siguiente ejemplo agrupa los documentos de la colección movies por el campo genres y calcula el recuento de cada valor distinto:

Aggregates.sortByCount("\$${Movie::genres.name}"),

Utilice el replaceRoot() método para crear una etapa de canalización $replaceRoot que reemplace cada documento de entrada con el documento especificado.

El siguiente ejemplo utiliza una colección books ficticia que contiene datos modelados utilizando la siguiente clase de datos Kotlin:

data class Libro(val titulo: String)
data class Book(val title: String, val spanishTranslation: Libro)

Cada documento de entrada se reemplaza por el documento anidado en el campo spanishTranslation:

Aggregates.replaceRoot("\$${Book::spanishTranslation.name}")

Utilice el addFields() método para crear una etapa de canalización $addFields que agregue nuevos campos a los documentos.

Tip

Utilice $addFields cuando no desee proyectar la inclusión o exclusión del campo.

El siguiente ejemplo añade dos nuevos campos, watched y type, a los documentos de entrada en la colección movie:

Aggregates.addFields(
Field("watched", false),
Field("type", "movie")
)

Utilice el count() método para crear una etapa de canalización $count que cuente el número de documentos que entran en ella y asigne ese valor a un nombre de campo específico. Si no especifica un campo, lo count() define como "count" por defecto.

Tip

La etapa $count es una azúcar sintáctica para:

{ "$group":{ "_id": 0, "count": { "$sum" : 1 } } }

El siguiente ejemplo crea una etapa de canalización que genera el recuento de documentos entrantes en un campo llamado "total":

Aggregates.count("total")

Utiliza el método bucket() para crear una etapa de pipeline $bucket que automatiza la agrupación de datos en torno a valores límite predefinidos.

Los siguientes ejemplos utilizan datos modelados con la siguiente clase de datos Kotlin:

data class Screen(
val id: String,
val screenSize: Int,
val manufacturer: String,
val price: Double
)

Este ejemplo crea una etapa de canalización que agrupa los documentos entrantes en función del valor de su campo screenSize, incluido el límite inferior y excluido el límite superior:

Aggregates.bucket("\$${Screen::screenSize.name}", listOf(0, 24, 32, 50, 70, 1000))

Utilice la clase BucketOptions para especificar un depósito predeterminado para valores fuera de los límites especificados y para especificar acumuladores adicionales.

El siguiente ejemplo crea una etapa de canalización que agrupa los documentos entrantes según el valor de su campo screenSize, contando la cantidad de documentos que caen dentro de cada contenedor, enviando el valor de screenSize a un campo llamado matches y capturando cualquier tamaño de pantalla mayor a "70" en un contenedor llamado "monstruo" para tamaños de pantalla monstruosamente grandes:

Tip

El controlador incluye la clase Accumulators con métodos de fábrica estáticos para cada uno de los acumuladores compatibles.

Aggregates.bucket("\$${Screen::screenSize.name}", listOf(0, 24, 32, 50, 70),
BucketOptions()
.defaultBucket("monster")
.output(
Accumulators.sum("count", 1),
Accumulators.push("matches", "\$${Screen::screenSize.name}")
)
)

Utilice el bucketAuto() método para crear una etapa de canalización $bucketAuto que determine automáticamente los límites de cada contenedor en su intento de distribuir los documentos de manera uniforme en una cantidad específica de contenedores.

Los siguientes ejemplos utilizan datos modelados con la siguiente clase de datos Kotlin:

data class Screen(
val id: String,
val screenSize: Int,
val manufacturer: String,
val price: Double
)

Este ejemplo crea una etapa de pipeline que intentará crear y distribuir de forma uniforme documentos en 5 compartimentos usando el valor de su campo price:

Aggregates.bucketAuto("\$${Screen::screenSize.name}", 5)

Utilice la BucketAutoOptions clase para especificar un esquema basado en números preferido para establecer valores límite y especificar acumuladores adicionales.

El siguiente ejemplo crea una etapa de canalización que intentará crear y distribuir uniformemente documentos en 5 grupos utilizando el valor de su campo price, estableciendo los límites de los grupos en potencias de 2 (2, 4, 8, 16, ...). También cuenta el número de documentos en cada grupo y calcula su promedio price en un nuevo campo llamado avgPrice:

Tip

El controlador incluye la clase Accumulators con métodos de fábrica estáticos para cada uno de los acumuladores compatibles.

Aggregates.bucketAuto(
"\$${Screen::price.name}", 5,
BucketAutoOptions()
.granularity(BucketGranularity.POWERSOF2)
.output(Accumulators.sum("count", 1), Accumulators.avg("avgPrice", "\$${Screen::price.name}"))
)

Utilice el facet() método para crear una etapa de canalización $facet que permita la definición de canalizaciones paralelas.

Los siguientes ejemplos utilizan datos modelados con la siguiente clase de datos Kotlin:

data class Screen(
val id: String,
val screenSize: Int,
val manufacturer: String,
val price: Double
)

Este ejemplo crea una etapa de canalización que ejecuta dos agregaciones paralelas:

  • La primera agregación distribuye los documentos entrantes en 5 grupos según su campo screenSize.

  • La segunda agregación cuenta todos los fabricantes y devuelve su recuento, limitado a los primeros 5.

Aggregates.facet(
Facet(
"Screen Sizes",
Aggregates.bucketAuto(
"\$${Screen::screenSize.name}",
5,
BucketAutoOptions().output(Accumulators.sum("count", 1))
)
),
Facet(
"Manufacturer",
Aggregates.sortByCount("\$${Screen::manufacturer.name}"),
Aggregates.limit(5)
)
)

Utilice el setWindowFields() método para crear una etapa de canalización $setWindowFields que permita usar operadores de ventana para realizar operaciones en un intervalo específico de documentos en una colección.

Tip

Funciones de ventana

El siguiente ejemplo utiliza una colección weather ficticia que utiliza datos modelados con la siguiente clase de datos Kotlin:

data class Weather(
val localityId: String,
val measurementDateTime: LocalDateTime,
val rainfall: Double,
val temperature: Double
)

El ejemplo crea una etapa de canalización que calcula la precipitación acumulada y la temperatura promedio durante el último mes para cada localidad a partir de mediciones más detalladas presentadas en los campos rainfall y temperature:

val pastMonth = Windows.timeRange(-1, MongoTimeUnit.MONTH, Windows.Bound.CURRENT)
val resultsFlow = weatherCollection.aggregate<Document>(
listOf(
Aggregates.setWindowFields("\$${Weather::localityId.name}",
Sorts.ascending(Weather::measurementDateTime.name),
WindowOutputFields.sum(
"monthlyRainfall",
"\$${Weather::rainfall.name}",
pastMonth
),
WindowOutputFields.avg(
"monthlyAvgTemp",
"\$${Weather::temperature.name}",
pastMonth
)
)
)

Utilice el densify() método para crear una etapa de canalización $densify que genere una secuencia de documentos para abarcar un intervalo específico.

Tip

Puede utilizar la etapa de agregación $densify() solo cuando ejecute MongoDB v5.1 o posterior.

Considere los siguientes documentos recuperados del conjunto de datos meteorológicos de muestra Atlas que contienen mediciones para un position campo similar, con una hora de diferencia:

Document{{ _id=5553a..., position=Document{{type=Point, coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:00:00 EST 1984, ... }}
Document{{ _id=5553b..., position=Document{{type=Point, coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 09:00:00 EST 1984, ... }}

Estos documentos se modelan utilizando la siguiente clase de datos de Kotlin:

data class Weather(
@BsonId val id: ObjectId = ObjectId(),
val position: Point,
val ts: LocalDateTime
)

Supongamos que necesita crear una etapa de canalización que realice las siguientes acciones en estos documentos:

  • Agregue un documento en cada intervalo de 15minutos para el cual aún no exista un valor ts.

  • Agrupe los documentos por el campo position.

La llamada al generador de la etapa de agregación densify() que realiza estas acciones debería parecerse a la siguiente:

Aggregates.densify(
"ts",
DensifyRange.partitionRangeWithStep(15, MongoTimeUnit.MINUTE),
DensifyOptions.densifyOptions().partitionByFields("Position.coordinates")
)

La siguiente salida resalta los documentos generados por la etapa agregada que contienen ts valores cada 15 minutos entre los documentos existentes:

Document{{ _id=5553a..., position=Document{{type=Point, coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:00:00 EST 1984, ... }}
Document{{ position=Document{{coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:15:00 EST 1984 }}
Document{{ position=Document{{coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:30:00 EST 1984 }}
Document{{ position=Document{{coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 08:45:00 EST 1984 }}
Document{{ _id=5553b..., position=Document{{type=Point, coordinates=[-47.9, 47.6]}}, ts=Mon Mar 05 09:00:00 EST 1984, ... }}

Consulte la documentación de la API del paquete densificar para obtener más información.

Utilice el fill() método para crear una etapa de canalización $fill que complete null y los valores de campo faltantes.

Tip

Puede utilizar la etapa de agregación $fill() solo cuando ejecute MongoDB v5.3 o posterior.

Considere los siguientes documentos que contienen mediciones de temperatura y presión del aire en un intervalo de una hora:

Document{{_id=6308a..., hour=1, temperature=23C, air_pressure=29.74}}
Document{{_id=6308b..., hour=2, temperature=23.5C}}
Document{{_id=6308c..., hour=3, temperature=null, air_pressure=29.76}}

Estos documentos se modelan utilizando la siguiente clase de datos de Kotlin:

data class Weather(
@BsonId val id: ObjectId = ObjectId(),
val hour: Int,
val temperature: String?,
val air_pressure: Double?
)

Supongamos que necesita completar los puntos de datos de temperatura y presión del aire faltantes en los documentos de la siguiente manera:

  • Complete el campo air_pressure para la hora "2" utilizando interpolación lineal para calcular el valor.

  • Establezca el valor temperature faltante en "23.6C" para la hora "3".

La llamada al generador de la etapa de agregación fill() que realiza estas acciones se parece a la siguiente:

val resultsFlow = weatherCollection.aggregate<Weather>(
listOf(
Aggregates.fill(
FillOptions.fillOptions().sortBy(Sorts.ascending(Weather::hour.name)),
FillOutputField.value(Weather::temperature.name, "23.6C"),
FillOutputField.linear(Weather::air_pressure.name)
)
)
)
resultsFlow.collect { println(it) }
Weather(id=6308a..., hour=1, temperature=23C, air_pressure=29.74)
Weather(id=6308b..., hour=2, temperature=23.5C, air_pressure=29.75)
Weather(id=6308b..., hour=3, temperature=23.6C, air_pressure=29.76)

Consulte la documentación de la API del paquete de relleno para obtener más información.

Utilice el search() método para crear una etapa de canalización $search que especifique una búsqueda de texto completo de uno o más campos.

Tip

Solo disponible en Atlas para MongoDB v4.2 y versiones posteriores

Este operador de canalización de agregación solo está disponible para colecciones alojadas en clústeres de MongoDB Atlas con la4.2 versión 7900 o posterior que estén cubiertos por un índice de MongoDB Search. Obtenga más información sobre la configuración necesaria y la funcionalidad de este operador en la documentación de MongoDB Search.

El siguiente ejemplo crea una etapa de canalización que busca en el campo title de la colección movies texto que contenga la palabra "Futuro":

Aggregates.search(
SearchOperator.text(
SearchPath.fieldPath(Movie::title.name), "Future"
),
SearchOptions.searchOptions().index("title")
)

Obtenga más información sobre los constructores en la documentación de la API del paquete de búsqueda.

El controlador Kotlin proporciona métodos auxiliares para los siguientes operadores:

Operador
Descripción

Realiza una búsqueda de una palabra o frase que contenga una secuencia de caracteres de una cadena de entrada incompleta.

Combina dos o más operadores en una sola consulta.

Comprueba si un campo coincide con el valor especificado. Se asigna a los métodos equals() y equalsNull().

Comprueba si existe una ruta a un nombre de campo indexado específico en un documento.

Realiza una búsqueda de una matriz de valores BSON de número, fecha, booleano, objectId, uuid o cadena en la ruta indicada y devuelve documentos donde el valor del campo es igual a cualquier valor en la matriz especificada.

Devuelve documentos similares a los documentos de entrada.

Admite la consulta y puntuación de valores numéricos, de fecha y de puntos GeoJSON.

Realiza una búsqueda de documentos que contienen una secuencia ordenada de términos utilizando el analizador especificado en la configuración del índice.

Brinda soporte a las queries de una combinación de campos indexados y valores.

Admite la consulta y puntuación de valores numéricos, de fecha y de cadena. Se asigna a los métodos numberRange() y dateRange().

Interpreta el campo de consulta como una expresión regular.

Realiza una búsqueda de texto completo utilizando el analizador que especifique en la configuración del índice.

Permite consultas que utilizan caracteres especiales en la cadena de búsqueda que pueden coincidir con cualquier carácter.

Nota

Conjunto de datos de muestra del Atlas

Este ejemplo utiliza la colección sample_mflix.movies de los conjuntos de datos de muestra de Atlas. Para aprender cómo configurar un clúster de Atlas de nivel gratuito y cargar el conjunto de datos de muestra, consulta el tutorial Empezar con Atlas en la documentación de Atlas.

Antes de poder ejecutar este ejemplo, debe crear un índice de búsqueda de MongoDB en la colección movies que tenga la siguiente definición:

{
"mappings": {
"dynamic": true,
"fields": {
"title": {
"analyzer": "lucene.keyword",
"type": "string"
},
"genres": {
"normalizer": "lowercase",
"type": "token"
}
}
}
}

Para obtener más información sobre la creación de índices de búsqueda de MongoDB, consulte la sección Índices de búsqueda de MongoDB y de búsqueda vectorial de MongoDB de la guía Índices.

El siguiente código crea una etapa $search que tiene las siguientes especificaciones:

  • Comprueba que la matriz genres incluye "Comedy"

  • Busca en el campo fullplot la frase "new york"

  • Coincide con year valores entre 1950 y 2000, inclusive

  • Busca title valores que comiencen con el término "Love"

data class Results(val title: String, val year: Int, val genres: List<String>)
val searchStage = Aggregates.search(
SearchOperator.compound()
.filter(
listOf(
SearchOperator.`in`(SearchPath.fieldPath(Movie::genres.name), listOf("Comedy")),
SearchOperator.phrase(SearchPath.fieldPath(Movie::fullplot.name), "new york"),
SearchOperator.numberRange(SearchPath.fieldPath(Movie::year.name)).gtLt(1950, 2000),
SearchOperator.wildcard(SearchPath.fieldPath(Movie::title.name), "Love *")
)
)
)
val projectStage = Aggregates.project(
Projections.include(Movie::title.name, Movie::year.name, Movie::genres.name))
val pipeline = listOf(searchStage, projectStage)
val resultsFlow = ftsCollection.aggregate<Results>(pipeline)
resultsFlow.collect { println(it) }
Results(title=Love at First Bite, year=1979, genres=[Comedy, Romance])
Results(title=Love Affair, year=1994, genres=[Comedy, Drama])

Para obtener más información sobre los métodos auxiliares de búsqueda de MongoDB, consulte la referencia de la interfaz SearchOperator en la documentación de la API de Driver Core.

Utilice el searchMeta() método para crear una etapa de canalización $searchMeta que devuelva solo la parte de metadatos de los resultados de las consultas de búsqueda de texto completo de Atlas.

Tip

Solo disponible en MongoDB Atlas v4.4.11 y versiones posteriores

Este operador de canalización de agregación solo está disponible para clústeres de MongoDB Atlas con la4.4.11 versión 7100 y posteriores. Para obtener una lista detallada de las versiones disponibles, consulte la documentación de MongoDB Atlas en $searchMeta.

El siguiente ejemplo muestra los metadatos count para una etapa de agregación de búsqueda de MongoDB:

Aggregates.searchMeta(
SearchOperator.near(1985, 2, SearchPath.fieldPath(Movie::year.name)),
SearchOptions.searchOptions().index("year")
)

Obtenga más información sobre este ayudante en la documentación de la API searchMeta().

Volver

Desarrolladores