Overview
En esta guía, aprenderá a usar intercalaciones con MongoDB para ordenar los resultados de sus consultas o agregaciones por valores de cadena. Una intercalación es un conjunto de reglas de ordenación y coincidencia de caracteres que se aplican a un idioma y una configuración regional específicos.
Puede obtener más información sobre las intercalaciones en las siguientes secciones de esta guía:
Datos de muestra para ejemplos
Los ejemplos de esta página utilizan una colección MongoDB con los siguientes documentos:
{ "_id" : 1, "firstName" : "Klara" } { "_id" : 2, "firstName" : "Gunter" } { "_id" : 3, "firstName" : "Günter" } { "_id" : 4, "firstName" : "Jürgen" } { "_id" : 5, "firstName" : "Hannah" }
Estos documentos son representados por la siguiente clase de datos:
data class FirstName( val id: Int, val firstName: String, val verified: Boolean = false )
Intercalaciones en MongoDB
MongoDB ordena las cadenas mediante intercalación binaria de forma predeterminada. Esta intercalación utiliza los valores de caracteres estándar ASCII para comparar y ordenar las cadenas. Algunos idiomas y configuraciones regionales tienen convenciones específicas de ordenación de caracteres que difieren de los valores de caracteres ASCII.
Por ejemplo, en francés canadiense, el carácter acentuado más a la derecha (diacrítico) determina el orden de las cadenas cuando todos los caracteres anteriores son iguales. Considere las siguientes palabras en francés canadiense:
redil
coté
côte
côté
Al utilizar la intercalación binaria, MongoDB los ordena en el siguiente orden:
cote coté côte côté
Al utilizar la intercalación francesa canadiense, MongoDB los ordena en un orden diferente como se muestra a continuación:
cote côte coté côté
Cómo especificar intercalaciones
MongoDB admite intercalaciones en la mayoría Operaciones CRUD y agregaciones. Para obtener una lista completa de las operaciones compatibles, consulte la página del manual del servidor "Operaciones compatibles con intercalaciones".
Puede especificar el código regional y la variante opcional en el siguiente formato de cadena:
"<locale code>@collation=<variant code>"
El siguiente ejemplo especifica el código de configuración regional "de" y el código de variante "phonebook":
"de@collation=phonebook"
Si no necesita especificar una variante, omita todo lo que esté después del código de configuración regional de la siguiente manera:
"de"
Para obtener una lista completa de las configuraciones regionales compatibles, consulte nuestra página del manual del servidor en Idiomas y configuraciones regionales compatibles.
Las siguientes secciones le muestran diferentes formas de aplicar intercalaciones en MongoDB:
Colección
Puede establecer una intercalación predeterminada al crear una colección. Al crear una colección con una intercalación específica, todas las operaciones compatibles que la analicen aplicarán las reglas de la intercalación.
Solo se puede asignar una Intercalación predeterminada a una colección al crear esa colección. Sin embargo, puedes especificar una intercalación en un nuevo índice de una colección existente. Consulta la sección Índice de esta guía para obtener más información.
El siguiente fragmento muestra cómo especificar la intercalación de configuración regional "en_US" al crear una nueva colección llamada items:
database.createCollection( "names", CreateCollectionOptions().collation( Collation.builder().locale("en_US").build() ) )
Para comprobar si ha creado la intercalación correctamente, recupere una lista de los índices de esa colección de la siguiente manera:
val collection = database.getCollection<FirstName>("names") val indexInformation = collection.listIndexes().first() println(indexInformation.toJson())
{ // ... "collation": { "locale": "en_US", // ... }, // ... }
Index
Puedes especificar una intercalación cuando creas un índice nuevo en una colección. El índice almacena una representación ordenada de los documentos en la colección, por lo que tu operación no necesita realizar el ordenamiento en la memoria. Para utilizar el índice, tu operación debe cumplir los siguientes criterios:
La operación utiliza la misma intercalación que la especificada en el índice.
La operación está cubierta por el índice que contiene la intercalación.
El siguiente fragmento de código muestra cómo crear un índice en el campo "firstName" con la intercalación de configuración regional "en_US" en orden ascendente:
val collection = database.getCollection<FirstName>("names") val idxOptions = IndexOptions().collation(Collation.builder().locale("en_US").build()) collection.createIndex(Indexes.ascending(FirstName::firstName.name), idxOptions)
Para comprobar si ha creado la intercalación correctamente, recupere una lista de los índices de esa colección de la siguiente manera:
val collection = database.getCollection<FirstName>("names") val indexInformation = collection.listIndexes().first() println(indexInformation.toJson())
{ // ... "collation": { "locale": "en_US", // ... }, // ... }
El siguiente fragmento de código muestra una operación de ejemplo que especifica la misma intercalación y está cubierta por el índice que creamos en el fragmento de código anterior:
val resultsFlow = collection.find() .collation(Collation.builder().locale("en_US").build()) .sort(Sorts.ascending(FirstName::firstName.name));
Operación
Puede anular la intercalación predeterminada de una colección pasando la nueva intercalación como parámetro a una de las operaciones compatibles. Sin embargo, dado que la operación no utiliza un índice, podría no tener el mismo rendimiento que una operación que sí lo esté. Para obtener más información sobre las desventajas de las operaciones de ordenación que no están incluidas en un índice, consulte la página del manual del servidor sobre el uso de índices para ordenar los resultados de las consultas.
El siguiente snippet de código muestra una operación de query de ejemplo con las siguientes características:
La colección referenciada contiene la intercalación predeterminada "en_US" similar a la especificada en la sección Colección.
La query especifica la intercalación islandesa («is»), que no está cubierta por el índice de intercalación por defecto de la colección.
Dado que la intercalación especificada no está cubierta por un índice, la operación de clasificación se realiza en la memoria.
val findFlow = collection.find() .collation(Collation.builder().locale("is").build()) .sort(Sorts.ascending(FirstName::firstName.name))
Tipos de índices que no admiten intercalaciones
Si bien la mayoría de los tipos de índice de MongoDB admiten la intercalación, los siguientes tipos solo admiten la comparación binaria:
Opciones de intercalación
Esta sección cubre varias opciones de intercalación y cómo especificarlas para refinar aún más el orden y el comportamiento de coincidencia.
Opción de intercalación | Descripción |
|---|---|
Configuración regional | Required. The ICU locale code for language and variant. locale() API Documentation |
Hacia atrás | Whether to consider diacritics from the end of the string first. backwards() API Documentation |
Sensibilidad a mayúsculas y minúsculas | Whether to consider case (upper or lower) as different values. caseLevel() API Documentation |
Alterno | Whether to consider spaces and punctuation. collationAlternate() API Documentation |
Caso Primero | Whether to consider uppercase or lowercase first. collationCaseFirst() API Documentation |
Variable máxima | Whether to ignore whitespace or both whitespace and punctuation. This setting is only valid when the alternate setting is "shifted". collationMaxVariable() API Documentation |
Fuerza | ICU level of comparison. The default value is "tertiary". For more information on each level, see the ICU Comparison Levels. collationStrength() API Documentation |
Normalización | Whether to perform unicode normalization on the text as needed. For more information on unicode normalization, see Unicode Normalization Forms. normalization() API Documentation |
Ordenamiento numérico | Whether to order numbers according to numeric value rather than collation order. numericOrdering() API Documentation |
Puede usar la clase Collation.Builder para especificar valores para las opciones de intercalación anteriores. Puede llamar al método build() para construir un objeto Collation, como se muestra en el siguiente fragmento de código:
Collation.builder() .caseLevel(true) .collationAlternate(CollationAlternate.SHIFTED) .collationCaseFirst(CollationCaseFirst.UPPER) .collationMaxVariable(CollationMaxVariable.SPACE) .collationStrength(CollationStrength.SECONDARY) .locale("en_US") .normalization(false) .numericOrdering(true) .build()
Para obtener más información sobre los métodos correspondientes y los parámetros que toman, consulte la Documentación de API para Collation.Builder.
Ejemplos de intercalación
Esta sección contiene ejemplos que demuestran cómo utilizar una selección de operaciones de MongoDB que admiten intercalaciones.
En los siguientes ejemplos, especificamos la configuración regional "de@collation=phonebook" y la intercalación de variantes. La parte "de" de la intercalación especifica la configuración regional alemana y la parte "collation=phonebook" especifica una variante. La intercalación de configuración regional "de" contiene reglas para priorizar los nombres propios, identificados por la mayúscula inicial. En la variante "collation=phonebook", los caracteres con diéresis se ordenan antes que los mismos caracteres sin diéresis, en orden ascendente.
Ejemplo de find() y sort()
El siguiente ejemplo muestra cómo aplicar una intercalación al recuperar resultados ordenados de una colección. Para ello, llame a find() en la colección de ejemplo y encadene los métodos collation() y sort() para especificar el orden en que desea recibir los resultados.
Cuando realizamos esta operación en nuestra colección de ejemplo, la salida debería ser similar a la siguiente:
val resultsFlow = collection.find() .collation(Collation.builder().locale("de@collation=phonebook").build()) .sort(Sorts.ascending(FirstName::firstName.name)) resultsFlow.collect { println(it) }
FirstName(id=3, firstName=Günter, verified=false) FirstName(id=2, firstName=Gunter, verified=false) FirstName(id=5, firstName=Hannah, verified=false) FirstName(id=4, firstName=Jürgen, verified=false) FirstName(id=1, firstName=Klara, verified=false)
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Ejemplo de findOneAndUpdate()
Esta sección muestra cómo especificar una intercalación en una operación que actualiza la primera coincidencia de la consulta. Para especificar la intercalación, cree una instancia de un objeto FindOneAndUpdateOptions, defínalo y páselo como parámetro al llamar al método findOneAndUpdate().
En este ejemplo, demostramos lo siguiente:
Recupere el primer documento de nuestra colección de ejemplo que precede a "Gunter" en orden ascendente.
Establezca opciones para la operación, incluida la intercalación
"de@collation=phonebook".Añade un nuevo campo “verificado” con el valor “verdadero”.
Recupere e imprima el documento actualizado.
Nota
El siguiente ejemplo de código utiliza importaciones del paquete import com.mongodb.client.model para mayor comodidad.
Dado que "Günter" está léxicamente antes de "Gunter" utilizando la de@collation=phonebook intercalación en orden ascendente, la siguiente operación devuelve "Günter" antes de "Gunter" en los resultados:
val result = collection.findOneAndUpdate( Filters.lt(FirstName::firstName.name, "Gunter"), Updates.set("verified", true), FindOneAndUpdateOptions() .collation(Collation.builder().locale("de@collation=phonebook").build()) .sort(Sorts.ascending(FirstName::firstName.name)) .returnDocument(ReturnDocument.AFTER) ) println(result)
FirstName(id=3, firstName=Günter, verified=true)
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Ejemplo de findOneAndDelete()
Esta sección muestra cómo especificar el orden numérico de las cadenas en una intercalación durante una operación que elimina la primera coincidencia de la consulta. Para especificar la intercalación, cree una instancia de un objeto FindOneAndDeleteOptions, defínale una intercalación de orden numérico y pásela como parámetro al llamar al método findOneAndDelete().
Este ejemplo llama a la operación findOneAndDelete() en una colección que contiene los siguientes documentos:
{ "_id" : 1, "a" : "16 apples" } { "_id" : 2, "a" : "84 oranges" } { "_id" : 3, "a" : "179 bananas" }
Estos documentos son representados por la siguiente clase de datos:
data class CollationExample( val id: Int, val a: String)
En la intercalación, establecemos la opción locale en "en" y la opción numericOrdering en "true" para ordenar las cadenas según su orden numérico.
Nota
El siguiente ejemplo de código utiliza importaciones del paquete import com.mongodb.client.model para mayor comodidad.
val result = collection.findOneAndDelete( Filters.gt(CollationExample::a.name, "100"), FindOneAndDeleteOptions() .collation(Collation.builder().locale("en").numericOrdering(true).build()) .sort(Sorts.ascending(CollationExample::a.name)) ) println(result)
CollationExample(id=3, a=179 bananas)
El valor numérico de la cadena "179" es mayor que el número 100, por lo que el documento anterior es la única coincidencia.
Si realizamos la misma operación sin la intercalación de orden numérico en la colección original de tres documentos, el filtro coincide con todos nuestros documentos ya que "100" viene antes de "16", "84" y "179" cuando se ordena por intercalación binaria.
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Ejemplo de agregación
Esta sección muestra cómo especificar una intercalación en una operación de agregación. En una operación de agregación, se puede especificar una serie de etapas de agregación, denominadas conjuntamente canalización de agregación. Para realizar una agregación, se llama al método aggregate() en un objeto MongoCollection.
Para especificar una intercalación para una operación de agregación, llame al método collation() en el valor AggregateFlow devuelto por la operación de agregación. Asegúrese de especificar una etapa de agregación de ordenación donde aplicar la intercalación en su canalización de agregación.
El siguiente ejemplo muestra cómo podemos construir una canalización de agregación en la colección de ejemplo y aplicar una intercalación especificando lo siguiente:
Una etapa de agregación de grupo que utiliza el ayudante
Aggregates.group()para identificar cada documento mediante el campofirstNamey utilizar ese valor como el_iddel resultado.Un acumulador en la etapa de agregación de grupo para sumar la cantidad de instancias de valores coincidentes en el campo
firstName.Aplicar una ordenación ascendente al campo
_idde los documentos de salida de la etapa de agregación anterior.Construya un objeto de intercalación, especificando la configuración regional alemana y un nivel de intercalación que ignore acentos y diéresis.
data class Result( val id: String, val nameCount: Int) val groupStage = Aggregates.group( "\$${FirstName::firstName.name}", Accumulators.sum("nameCount", 1) ) val sortStage = Aggregates.sort(Sorts.ascending("_id")) val resultsFlow = collection.aggregate<Result>(listOf(groupStage, sortStage)) .collation( Collation.builder().locale("de") .collationStrength(CollationStrength.PRIMARY) .build() ) resultsFlow.collect { println(it) }
Result(id=Gunter, nameCount=2) Result(id=Hannah, nameCount=1) Result(id=Jürgen, nameCount=1) Result(id=Klara, nameCount=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: