Overview
En esta guía, podrá aprender a utilizar operaciones de agregación en el controlador de Kotlin.
Las operaciones de agregación procesan datos en tus colecciones de MongoDB y devuelven resultados calculados. El pipeline de agregación de MongoDB, que forma parte de la API de query, está modelado con el concepto de pipelines de procesamiento de datos. Los documentos ingresan a una pipeline de múltiples etapas que transforma los documentos en un resultado agregado.
Tip
Tutoriales completos sobre agregación
Puedes encontrar tutoriales que proporcionan explicaciones detalladas de tareas de agregación comunes en el Tutoriales completos del pipeline de agregación en el manual del servidor. Selecciona un tutorial y luego elige Kotlin (Coroutine) en 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 lo que ocurre en una fábrica de autos. Dentro de la fábrica de automóviles hay una línea de montaje, a lo largo de la cual hay estaciones de ensamblaje con herramientas especializadas para realizar una tarea específica, como taladros y soldadoras. Las piezas en bruto ingresan a la fábrica, y la fábrica las transforma y ensambla en 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:
seleccionar qué documentos devolver
seleccionar qué campos devolver
ordenar los resultados
Al utilizar las operaciones de aggregation, puedes:
realizar todas las operaciones de
findcambiar el nombre de los campos
calcular campos
resumir datos
valores grupales
Las operaciones de agregación tienen algunas limitaciones que debe 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 driver de Kotlin proporciona la clase asistente Aggregates que contiene desarrolladores para etapas de agregación.
En el siguiente ejemplo, la canalización de agregación:
Utiliza una etapa $match para filtrar documentos cuyo campo de tipo arreglo
categoriescontenga el elementoBakery. El ejemplo utilizaAggregates.matchpara compilar la etapa$match.Utiliza una etapa $group para agrupar los documentos coincidentes por el
starscampo, acumulando un recuento de documentos para cada valor distintostarsde.
Tip
Puede compilar las expresiones que se utilizan en este ejemplo mediante los desarrolladores 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 la 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.
Puedes especificar el nivel de detalle de tu 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. |
EXECUTION_STATS | Tu quieres saber si tu query está funcionando bien. |
QUERY_PLANNER | 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, consulta los siguientes recursos:
Explicar salida Entrada manual del servidor
Planes de consulta Entrada del manual del servidor
Documentación de la API deExplainVerbosity
Documentación de la APIexplain()
AggregateFlow Documentación API
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 "categories" le indica a MongoDB que se trata de una ruta de campo, utilizando el campo "categories" del documento de entrada.
Document("\$arrayElemAt", listOf("\$categories", 0)) // is equivalent to Document.parse("{ \$arrayElemAt: ['\$categories', 0] }")
En el siguiente ejemplo, la pipeline de agregación utiliza una $project etapa 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 la API: