Overview
En esta guía, puedes aprender a usar operaciones de ordenación para organizar los resultados de tus operaciones de lectura con el controlador MongoDB Kotlin.
La operación de ordenamiento ordena los documentos devueltos por tu consulta según tus criterios de clasificación especificados. Los criterios de ordenación son las reglas que se pasan a MongoDB y que describen cómo se quiere ordenar los datos. Algunos ejemplos de criterios de ordenación son:
Del menor número al mayor número
Desde la hora más temprana del día hasta la hora más tardía del día
Orden alfabético por nombre
Deberías leer esta guía para aprender cómo realizar las siguientes acciones:
Realiza ordenamientos ascendentes y descendentes
Combinar criterios de ordenación
Ordenar según la puntuación de texto de un query de texto
Los ejemplos en esta guía utilizan una colección de muestra que incluye los siguientes documentos:
{ "_id": 1, "date": "2022-01-03", "orderTotal": 17.86, "description": "1/2 lb cream cheese and 1 dozen bagels" }, { "_id": 2, "date": "2022-01-11", "orderTotal": 83.87, "description": "two medium vanilla birthday cakes" }, { "_id": 3, "date": "2022-01-11", "orderTotal": 19.49, "description": "1 dozen vanilla cupcakes" }, { "_id": 4, "date": "2022-01-15", "orderTotal": 43.62, "description": "2 chicken lunches and a diet coke" }, { "_id": 5, "date": "2022-01-23", "orderTotal": 60.31, "description": "one large vanilla and chocolate cake" }, { "_id": 6, "date": "2022-01-23", "orderTotal": 10.99, "description": "1 bagel, 1 orange juice, 1 muffin" }
Estos datos se modelan con la siguiente clase de datos de Kotlin:
data class Order( val id: Int, val date: String, val orderTotal: Double, val description: String, )
Métodos de ordenación
Puedes ordenar los resultados recuperados por una query o puedes ordenar los resultados dentro de un pipeline de agregación.
Para ordenar los resultados de la consulta, utiliza el
sort() método de una instancia de FindFlow. Para ordenar sus resultados dentro de un pipeline de agregación, utilice el método de fábrica estático Aggregates.sort(). Ambos métodos reciben objetos que implementan la interfaz Bson como argumentos. Para obtener más información, consulta la documentación de la API para la Interfaz BSON.
Puedes usar el método sort() de una instancia de FindFlow de la siguiente manera:
val resultsFlow = collection.find().sort(Sorts.ascending(Order::orderTotal.name))
Puedes utilizar el método Aggregates.sort() dentro de un pipeline de agregación para ordenar los documentos en la colección de muestra de menor a mayor valor del campo orderTotal, de la siguiente manera:
val resultsFlow = collection.aggregate(listOf( Aggregates.sort(Sorts.ascending(Order::orderTotal.name)) )) resultsFlow.collect { println(it) }
Order(id=6, date=2022-01-23, orderTotal=10.99, description=1 bagel, 1 orange juice, 1 muffin) Order(id=1, date=2022-01-03, orderTotal=17.86, description=1/2 lb cream cheese and 1 dozen bagels) Order(id=3, date=2022-01-11, orderTotal=19.49, description=1 dozen vanilla cupcakes) Order(id=4, date=2022-01-15, orderTotal=43.62, description=2 chicken lunches and a diet coke) Order(id=5, date=2022-01-23, orderTotal=60.31, description=one large vanilla and chocolate cake) Order(id=2, date=2022-01-11, orderTotal=83.87, description=two medium vanilla birthday cakes)
En los fragmentos de código anteriores, especificamos los criterios de ordenación utilizando la clase Sorts builder. Si bien es posible especificar criterios de orden mediante cualquier clase que implemente la interfaz Bson, recomendamos que los criterios de orden se especifiquen mediante el desarrollador Sorts. Para obtener más información sobre la clase builder Sorts, consulta la Guía del generador de ordenamientos.
Para obtener más información sobre las clases e interfaces en esta sección, consulte la siguiente documentación de API:
Dirección de clasificación
La dirección de tu ordenamiento puede ser ascendente o descendente. Un orden ascendente organiza tus resultados de menor a mayor. Una ordenación descendente organiza tus resultados de mayor a menor.
Aquí tienes algunos ejemplos de datos ordenados en forma ascendente:
Numbers: 1, 2, 3, 43, 43, 55, 120
Dates: 1990-03-10, 1995-01-01, 2005-10-30, 2005-12-21
Palabras (ASCII): Banana, Eneldo, zanahoria, pepino, hummus
Aquí tienes algunos ejemplos de datos ordenados en orden descendente:
Numbers: 100, 30, 12, 12, 9, 3, 1
Dates: 2020-01-01, 1998-12-11, 1998-12-10, 1975-07-22
Palabras (ASCII inverso): pera, uvas, manzana, Queso
Las siguientes subsecciones muestran cómo especificar estos criterios de clasificación.
Ascendente
Para especificar un orden ascendente, utiliza el método de la fábrica estática Sorts.ascending(). Pasa a Sorts.ascending() el nombre del campo que necesitas ordenar en orden ascendente.
Puede pasar el método sort() la salida del método Sorts.ascending() para especificar una ordenación ascendente en un campo de la siguiente manera:
collection.find().sort(Sorts.ascending("<field name>"))
El método sort() precedente devuelve un objeto FindIterable que puede iterar sobre los documentos de tu colección, ordenados de menor a mayor según el nombre del campo especificado.
En el siguiente ejemplo de código, utilizamos el método ascending() para ordenar la colección de muestras por el campo orderTotal:
val resultsFlow = collection.find() .sort(Sorts.ascending(Order::orderTotal.name)) resultsFlow.collect { println(it) }
Order(id=6, date=2022-01-23, orderTotal=10.99, description=1 bagel, 1 orange juice, 1 muffin) Order(id=1, date=2022-01-03, orderTotal=17.86, description=1/2 lb cream cheese and 1 dozen bagels) Order(id=3, date=2022-01-11, orderTotal=19.49, description=1 dozen vanilla cupcakes) Order(id=4, date=2022-01-15, orderTotal=43.62, description=2 chicken lunches and a diet coke) Order(id=5, date=2022-01-23, orderTotal=60.31, description=one large vanilla and chocolate cake) Order(id=2, date=2022-01-11, orderTotal=83.87, description=two medium vanilla birthday cakes)
Descendente
Para especificar una clasificación descendente, use el método de fábrica estático Sorts.descending(). Pase al método Sorts.descending() el nombre del campo que necesita ordenar en orden descendente.
El siguiente fragmento de código muestra cómo especificar una ordenación descendente en el campo orderTotal y devolver los documentos de la colección de muestra en orden descendente:
val resultsFlow = collection.find() .sort(Sorts.descending(Order::orderTotal.name)) resultsFlow.collect { println(it) }
Order(id=2, date=2022-01-11, orderTotal=83.87, description=two medium vanilla birthday cakes) Order(id=5, date=2022-01-23, orderTotal=60.31, description=one large vanilla and chocolate cake) Order(id=4, date=2022-01-15, orderTotal=43.62, description=2 chicken lunches and a diet coke) Order(id=3, date=2022-01-11, orderTotal=19.49, description=1 dozen vanilla cupcakes) Order(id=1, date=2022-01-03, orderTotal=17.86, description=1/2 lb cream cheese and 1 dozen bagels) Order(id=6, date=2022-01-23, orderTotal=10.99, description=1 bagel, 1 orange juice, 1 muffin)
Manejo de empates
Se produce un empate cuando dos o más documentos tienen valores idénticos en el campo que se utiliza para ordenar los resultados. MongoDB no garantiza el orden de clasificación en caso de evento de empates. Por ejemplo, supongamos que encontramos un empate al ordenar la colección de muestras utilizando el siguiente código:
collection.find().sort(Sorts.ascending(Order::date.name))
Dado que varios documentos que se ajustan a la query contienen el mismo valor en el campo date, es posible que los documentos no se devuelvan en un orden coherente.
Si necesitas garantizar un orden específico para documentos cuyos campos tienen valores idénticos, puedes especificar campos adicionales para ordenar en caso de empate.
Podemos especificar un ordenamiento ascendente en el campo date seguido del campo orderTotal para devolver los documentos en la colección de muestra en el siguiente orden:
collection.find().sort(Sorts.ascending(Order::date.name, Order::orderTotal.name))
Order(id=1, date=2022-01-03, orderTotal=17.86, description=1/2 lb cream cheese and 1 dozen bagels) Order(id=3, date=2022-01-11, orderTotal=19.49, description=1 dozen vanilla cupcakes) Order(id=2, date=2022-01-11, orderTotal=83.87, description=two medium vanilla birthday cakes) Order(id=4, date=2022-01-15, orderTotal=43.62, description=2 chicken lunches and a diet coke) Order(id=6, date=2022-01-23, orderTotal=10.99, description=1 bagel, 1 orange juice, 1 muffin) Order(id=5, date=2022-01-23, orderTotal=60.31, description=one large vanilla and chocolate cake)
Combinación de criterios de ordenación
Para combinar los criterios de ordenación, utiliza el método de fábrica estático Sorts.orderBy(). Este método construye un objeto que contiene una lista ordenada de criterios de clasificación. Al realizar la clasificación, si los criterios de clasificación anteriores generan un empate, la clasificación utiliza los siguientes criterios de clasificación en la lista para determinar el orden.
En el siguiente fragmento de código, utilizamos el método orderBy() para ordenar los datos realizando un orden descendente en el campo date y, en el evento de un empate, realizando un orden ascendente en el campo orderTotal. Con estos criterios de clasificación, el código devuelve los documentos en la colección de muestra en el siguiente orden:
val orderBySort = Sorts.orderBy( Sorts.descending(Order::date.name), Sorts.ascending(Order::orderTotal.name) ) val results = collection.find().sort(orderBySort) results.collect {println(it) }
Order(id=6, date=2022-01-23, orderTotal=10.99, description=1 bagel, 1 orange juice, 1 muffin) Order(id=5, date=2022-01-23, orderTotal=60.31, description=one large vanilla and chocolate cake) Order(id=4, date=2022-01-15, orderTotal=43.62, description=2 chicken lunches and a diet coke) Order(id=3, date=2022-01-11, orderTotal=19.49, description=1 dozen vanilla cupcakes) Order(id=2, date=2022-01-11, orderTotal=83.87, description=two medium vanilla birthday cakes) Order(id=1, date=2022-01-03, orderTotal=17.86, description=1/2 lb cream cheese and 1 dozen bagels)
Text query
Puedes especificar el orden de los resultados de una query de texto según la proximidad con la que los valores de string de cada campo de resultado especificados por el índice de texto de la colección coincidan con tu string de búsqueda. La query de texto asigna un puntaje de texto numérico para indicar qué tan de cerca coincide cada resultado con la search string. Utiliza el método de fábrica estático Sorts.metaTextScore() para compilar tus criterios de ordenación y ordenar por el puntaje textual.
Importante
Asegúrate de crear un índice de texto
Necesita un índice de texto en su colección para realizar una query de texto. Consulta la documentación del manual del servidor para obtener más información sobre cómo crear un índice de texto.
En el siguiente ejemplo de código, te mostramos cómo puedes usar el método Sorts.metaTextScore() para ordenar los resultados de una búsqueda de texto en la Colección de ejemplo. El ejemplo de código utiliza los desarrolladores de Filtros, Índices y Proyecciones.
El ejemplo de código realiza las siguientes acciones:
Crea un índice de texto para tu colección de muestras en el campo
description. Si llamas acreateIndex()especificando un índice que ya existe en la colección, la operación no crea un índice nuevo.Ejecuta tu consulta de texto para la frase
"vanilla".Proyecta las puntuaciones de texto en los resultados de la consulta como el campo
score.Ordena tus resultados por puntuación de texto (la mejor coincidencia primero).
Los datos se modelan con la siguiente clase de datos de Kotlin:
data class OrderScore( val id: Int, val description: String, val score: Double )
import com.mongodb.client.model.Sorts import com.mongodb.client.model.Projections import com.mongodb.client.model.Filters import com.mongodb.client.model.Indexes
collection.createIndex(Indexes.text(Order::description.name)) val metaTextScoreSort = Sorts.orderBy( Sorts.metaTextScore(OrderScore::score.name), Sorts.descending("_id") ) val metaTextScoreProj = Projections.metaTextScore(OrderScore::score.name) val searchTerm = "vanilla" val searchQuery = Filters.text(searchTerm) val results = collection.find<OrderScore>(searchQuery) .projection(metaTextScoreProj) .sort(metaTextScoreSort) results.collect { println(it) }
OrderScore(id=3, description=1 dozen vanilla cupcakes, score=0.625) OrderScore(id=5, description=one large vanilla and chocolate cake, score=0.6) OrderScore(id=2, description=two medium vanilla birthday cakes, score=0.6)
Nota
Comportamiento de query de texto en MongoDB 4.4 o posterior
La estructura de consulta de texto ha cambiado para MongoDB 4.4 o posterior. Ya no es necesario proyectar Projections.metaTextScore() en tu instancia de FindFlow para ordenar por la puntuación de texto. Además, el nombre del campo que se especifica en una operación de agregación de puntaje de texto $meta, utilizada en una ordenación, se ignora. Esto significa que el argumento del nombre del campo que se pasa a Sorts.metaTextScore() se ignora.
Para más información sobre las clases en esta sección, consulta la siguiente Documentación de la API:
Para obtener más información, consulta la clase Sorts Documentación de la API. Consulte la documentación del manual del servidor para obtener más información sobre el operador del query $text y el operador del pipeline de agregación $meta.