Overview
En esta guía, puedes aprender cómo utilizar intercalaciones con MongoDB para ordenar los resultados de tu consulta u operación de agregación por valores de strings. Una intercalación es un conjunto de reglas de ordenamiento y coincidencia de caracteres que se aplican a un idioma y localización específicos.
Puedes aprender más sobre 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 el 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. Considera las siguientes palabras en francés canadiense:
redil
coté
côte
côté
Cuando se utiliza una 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 es compatible con la intercalación en la mayoría de los casos Operaciones CRUD y agregaciones. Para obtener una lista completa de las operaciones compatibles, consulta el Operaciones que admiten intercalaciones Manual del servidor.
Puedes especificar el código de localización y variante opcional en el siguiente formato de string:
"<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 se necesita especificar una variante, omitir todo lo que hay después del código de localización, como sigue:
"de"
Para ver una lista completa de las localizaciones admitidas, consulta nuestra página del manual de servidor sobre Lenguajes y localizaciones admitidos.
Las siguientes secciones 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 snippet muestra cómo especificar la intercalació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 creó la intercalación correctamente, obtenga una lista de los índices en 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 snippet muestra cómo se puede crear un índice en el campo "firstName" con la intercalación de localización "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 creó la intercalación correctamente, obtenga una lista de los índices en 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 snippet muestra un ejemplo de operación que especifica la misma intercalación y está cubierto por el índice que creamos en el snippet anterior:
val resultsFlow = collection.find() .collation(Collation.builder().locale("en_US").build()) .sort(Sorts.ascending(FirstName::firstName.name));
Operación
Puedes anular la intercalación por defecto en una colección pasando la nueva intercalación como un parámetro a una de las operaciones admitidas. Sin embargo, como la operación no utiliza un índice, la operación puede no funcionar tan bien como una cubierta por un índice. Para obtener más información sobre las desventajas de las operaciones de ordenación no cubiertas por un índice, consulta la página del manual del servidor sobre Utiliza los índices para ordenar los resultados de la query.
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 por defecto "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 ordenación se realiza en la memoria.
val findFlow = collection.find() .collation(Collation.builder().locale("is").build()) .sort(Sorts.ascending(FirstName::firstName.name))
Tipos de índice que no admiten intercalaciones
Aunque la mayoría de los tipos de índices de MongoDB admiten la intercalación, los siguientes tipos admiten únicamente la comparación binaria:
Opciones de intercalación
Esta sección abarca diversas opciones de intercalación y cómo especificarlas para refinar aún más el comportamiento de intercalación y comparación.
Opción de intercalación | Descripción |
|---|---|
localización | 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 |
Alternativo | 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 emplean, consulta la Documentación de la API de intercalación.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.
find() and sort() Example
El siguiente ejemplo demuestra cómo se puede aplicar una intercalación al recuperar resultados ordenados de una colección. Para realizar esta operación, llama a find() en la colección de ejemplos y encadena los métodos collation() y sort() para especificar el orden en el que deseas 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 la API:
Ejemplo de findOneAndUpdate()
Esta sección muestra cómo se puede especificar una intercalación en una operación que actualiza la primera coincidencia de su query. Para especificar la intercalación de esta operación, instancie un objeto FindOneAndUpdateOptions, establezca una intercalación en él y páselo como parámetro en su llamada 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.
Configura opciones para la operación, incluyendo 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 la API:
Ejemplo de findOneAndDelete()
Esta sección demuestra cómo puedes especificar un orden numérico de cadenas en una intercalación en una operación que elimina la primera coincidencia de tu query. Para especificar la intercalación para esta operación, instancie un objeto FindOneAndDeleteOptions, establezca una ordenación numérica en él y páselo como parámetro a su llamada 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 "verdadero" para ordenar cadenas en función de 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 que "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 la API:
Ejemplo de agregación
Esta sección demuestra cómo se puede especificar una intercalación en una operación de agregación. En una operación de agrupación, puedes especificar una serie de etapas de agregación que colectivamente se denominan el pipeline de agregación. Para realizar una agregación, llama al método aggregate() en un objeto MongoCollection.
Para especificar una intercalación para una operación de agregación, llama al método collation() en el AggregateFlow devuelto por la operación de agregación. Asegúrate de especificar una etapa de agregación de ordenamiento sobre la cual aplicar la intercalación en tu pipeline de agregación.
El siguiente ejemplo muestra cómo podemos construir un pipeline 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
Aggregates.group()asistente para identificar cada documento por el campofirstNamey usar ese valor como el_iddel resultado.Un acumulador en la etapa de agregación de grupo para sumar el número 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 localización alemana y una fuerza de intercalación que ignore los acentos y las 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 la API: