Overview
En esta guía, puede aprender a utilizar operaciones de agregación en el controlador Kotlin.
Las operaciones de agregación procesan los datos de sus colecciones de MongoDB y devuelven resultados calculados. La canalización de agregación de MongoDB, que forma parte de la API de consultas, se basa en el concepto de canalizaciones de procesamiento de datos. Los documentos entran en una canalización de varias etapas que los transforma en un resultado agregado.
Tip
Tutoriales completos sobre agregación
Puede encontrar tutoriales que brindan explicaciones detalladas de tareas de agregación comunes en Sección completa de tutoriales decanalización de agregación del manual del servidor. Seleccione un tutorial y luego seleccione Kotlin (Coroutine) desde el menú desplegable Select your language en la esquina superior derecha de la página.
Analogía
La funcionalidad de una agregación es similar a la de una fábrica de automóviles. Dentro de la fábrica hay una línea de montaje, a lo largo de la cual se ubican estaciones de ensamblaje con herramientas especializadas para realizar una tarea específica, como taladros y soldadores. Las piezas en bruto entran en la fábrica, donde se transforman y ensamblan para obtener un producto terminado.
La tubería de agregación es la línea de ensamblaje, las etapas de agregación son las estaciones de ensamblaje y las expresiones del operador son las herramientas especializadas.
Comparación de operaciones de agregación y búsqueda
Utilizando find operaciones, puedes:
Seleccione qué documentos devolver
Seleccione qué campos devolver
ordenar los resultados
Utilizando operaciones aggregation, puedes:
realizar todas las
findoperacionescambiar el nombre de los campos
calcular campos
resumir datos
valores grupales
Las operaciones de agregación tienen algunas limitaciones que debes tener en cuenta:
Los documentos devueltos no deben violar el límite de tamaño de documento BSON de 16 megabytes.
Las etapas de pipeline tienen un límite de memoria de 100 megabytes por defecto. Si es necesario, puede superar este límite con el método allowDiskUse.
Importante
Excepción $graphLookup
La etapa $graphLookup tiene un límite de memoria estricto de 100 megabytes e
allowDiskUseignorará.
Referencias útiles
Datos de ejemplo
Los ejemplos utilizan una colección de los siguientes datos en MongoDB:
[ {"name": "Sun Bakery Trattoria", "contact": {"phone": "386-555-0189", "email": "SunBakeryTrattoria@example.org", "location": [-74.0056649, 40.7452371]}, "stars": 4, "categories": ["Pizza", "Pasta", "Italian", "Coffee", "Sandwiches"]}, {"name": "Blue Bagels Grill", "contact": {"phone": "786-555-0102", "email": "BlueBagelsGrill@example.com", "location": [-73.92506, 40.8275556]}, "stars": 3, "categories": ["Bagels", "Cookies", "Sandwiches"]}, {"name": "XYZ Bagels Restaurant", "contact": {"phone": "435-555-0190", "email": "XYZBagelsRestaurant@example.net", "location": [-74.0707363, 40.59321569999999]}, "stars": 4, "categories": ["Bagels", "Sandwiches", "Coffee"]}, {"name": "Hot Bakery Cafe", "contact": {"phone": "264-555-0171", "email": "HotBakeryCafe@example.net", "location": [-73.96485799999999, 40.761899]}, "stars": 4, "categories": ["Bakery", "Cafe", "Coffee", "Dessert"]}, {"name": "Green Feast Pizzeria", "contact": {"phone": "840-555-0102", "email": "GreenFeastPizzeria@example.com", "location": [-74.1220973, 40.6129407]}, "stars": 2, "categories": ["Pizza", "Italian"]}, {"name": "ZZZ Pasta Buffet", "contact": {"phone": "769-555-0152", "email": "ZZZPastaBuffet@example.com", "location": [-73.9446421, 40.7253944]}, "stars": 0, "categories": ["Pasta", "Italian", "Buffet", "Cafeteria"]}, {"name": "XYZ Coffee Bar", "contact": {"phone": "644-555-0193", "email": "XYZCoffeeBar@example.net", "location": [-74.0166091, 40.6284767]}, "stars": 5, "categories": ["Coffee", "Cafe", "Bakery", "Chocolates"]}, {"name": "456 Steak Restaurant", "contact": {"phone": "990-555-0165", "email": "456SteakRestaurant@example.com", "location": [-73.9365108, 40.8497077]}, "stars": 0, "categories": ["Steak", "Seafood"]}, {"name": "456 Cookies Shop", "contact": {"phone": "604-555-0149", "email": "456CookiesShop@example.org", "location": [-73.8850023, 40.7494272]}, "stars": 4, "categories": ["Bakery", "Cookies", "Cake", "Coffee"]}, {"name": "XYZ Steak Buffet", "contact": {"phone": "229-555-0197", "email": "XYZSteakBuffet@example.org", "location": [-73.9799932, 40.7660886]}, "stars": 3, "categories": ["Steak", "Salad", "Chinese"]} ]
Los datos de la colección están modelados por la siguiente clase de datos Restaurant:
data class Restaurant( val name: String, val contact: Contact, val stars: Int, val categories: List<String> ) { data class Contact( val phone: String, val email: String, val location: List<Double> ) }
Agregación básica
Para realizar una agregación, pase una lista de etapas de agregación al método MongoCollection.aggregate().
El controlador Kotlin proporciona la clase auxiliar Aggregates que contiene constructores para las etapas de agregación.
En el siguiente ejemplo, la canalización de agregación:
Utiliza la etapa $match para filtrar documentos cuyo
categoriescampo de matriz contiene elBakeryelemento. El ejemplo utilizaAggregates.matchpara generar la$matchetapa.Utiliza una etapa $group para agrupar los documentos coincidentes por el
starscampo, acumulando un recuento de documentos para cada valor distintostarsde.
Tip
Puede crear las expresiones utilizadas en este ejemplo utilizando los constructores de agregación.
data class Results( val id: Int, val count: Int) val resultsFlow = collection.aggregate<Results>( listOf( Aggregates.match(Filters.eq(Restaurant::categories.name, "Bakery")), Aggregates.group( "\$${Restaurant::stars.name}", Accumulators.sum("count", 1) ) ) ) resultsFlow.collect { println(it) }
Results(id=4, count=2) Results(id=5, count=1)
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Explicar la agregación
Para ver información sobre cómo MongoDB ejecuta su operación, utilice el explain() método de la AggregateFlow clase. El explain() método devuelve planes de ejecución y estadísticas de rendimiento. Un plan de ejecución es una forma en que MongoDB puede completar una operación. El explain() método proporciona tanto el plan ganador (el plan ejecutado por MongoDB) como los planes rechazados.
Puede especificar el nivel de detalle de su explicación pasando un nivel de verbosidad al método explain().
La siguiente tabla muestra todos los niveles de verbosidad para las explicaciones y sus casos de uso previstos:
Nivel de verbosidad | Caso de uso |
|---|---|
TODAS LAS EJECUCIONES DE LOS PLANES | Desea saber qué plan elegirá MongoDB para ejecutar su consulta. |
ESTADÍSTICAS DE EJECUCIÓN | Quiere saber si su consulta está funcionando bien. |
PLANIFICADOR DE CONSULTAS | Tienes un problema con tu query y quieres la mayor cantidad de información posible para diagnosticar el problema. |
En el siguiente ejemplo, imprimimos la representación JSON de los planes ganadores para las etapas de agregación que producen planes de ejecución:
data class Results(val name: String, val count: Int) val explanation = collection.aggregate<Results>( listOf( Aggregates.match(Filters.eq(Restaurant::categories.name, "bakery")), Aggregates.group("\$${Restaurant::stars.name}", Accumulators.sum("count", 1)) ) ).explain(ExplainVerbosity.EXECUTION_STATS) // Prettyprint the output println(explanation.toJson(JsonWriterSettings.builder().indent(true).build()))
{ "explainVersion": "2", "queryPlanner": { // ... }, "command": { // ... }, // ... }
Para obtener más información sobre los temas mencionados en esta sección, consulte los siguientes recursos:
Explicar la entrada manual del servidor de salida
Documentación de la API deExplainVerbosity
Documentación de la APIexplain()
Documentación de la API deAggregateFlow
Expresiones de agregación
El controlador Kotlin proporciona constructores para expresiones de acumulador que se usan con $group. Debe declarar todas las demás expresiones en formato JSON o en un formato de documento compatible.
Tip
La sintaxis en cualquiera de los siguientes ejemplos definirá una expresión $arrayElemAt.
El $ delante de "categorías" le indica a MongoDB que se trata de una ruta de campo, que utiliza el campo "categorías" del documento de entrada.
Document("\$arrayElemAt", listOf("\$categories", 0)) // is equivalent to Document.parse("{ \$arrayElemAt: ['\$categories', 0] }")
En el siguiente ejemplo, la canalización de agregación utiliza una etapa $project y varios Projections para devolver el campo name y el campo calculado firstCategory cuyo valor es el primer elemento del campo categories.
data class Results(val name: String, val firstCategory: String) val resultsFlow = collection.aggregate<Results>( listOf( Aggregates.project( Projections.fields( Projections.excludeId(), Projections.include("name"), Projections.computed( "firstCategory", Document("\$arrayElemAt", listOf("\$categories", 0)) ) ) ) ) ) resultsFlow.collect { println(it) }
Results(name=Sun Bakery Trattoria, firstCategory=Pizza) Results(name=Blue Bagels Grill, firstCategory=Bagels) Results(name=XYZ Bagels Restaurant, firstCategory=Bagels) Results(name=Hot Bakery Cafe, firstCategory=Bakery) Results(name=Green Feast Pizzeria, firstCategory=Pizza) Results(name=ZZZ Pasta Buffet, firstCategory=Pasta) Results(name=XYZ Coffee Bar, firstCategory=Coffee) Results(name=456 Steak Restaurant, firstCategory=Steak) Results(name=456 Cookies Shop, firstCategory=Bakery) Results(name=XYZ Steak Buffet, firstCategory=Steak)
Documentación de la API
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API: