Overview
En esta guía, puede aprender a crear y administrar índices mediante el controlador MongoDB Kotlin.
Los índices facilitan la ejecución eficiente de consultas en MongoDB. Sin índices, MongoDB debe escanear todos los documentos de una colección (un escaneo de colección) para encontrar los documentos que coinciden con cada consulta. Estos escaneos de colección son lentos y pueden afectar negativamente el rendimiento de la aplicación. Si existe un índice adecuado para una consulta, MongoDB puede usarlo para limitar los documentos que la consulta debe inspeccionar.
Los índices también ofrecen los siguientes beneficios:
Los índices permiten una clasificación eficiente.
Los índices permiten capacidades especiales como consultas geoespaciales.
Losíndices permiten la creación de restricciones para garantizar que un valor de campo sea único.
Para obtener más información, consulte Índices en el manual del servidor.
Tip
Las operaciones de actualización utilizan índices al buscar documentos para actualizar, y las operaciones de eliminación utilizan índices al buscar documentos para eliminar. Ciertas etapas del proceso de agregación también utilizan índices para mejorar el rendimiento.
Cobertura y rendimiento de las consultas
Cuando ejecuta una consulta en MongoDB, su comando puede incluir varios elementos:
Criterios de consulta que especifican los campos y valores que estás buscando
Opciones que afectan la ejecución de la consulta, como la preocupación de lectura
Criterios de proyección para especificar los campos que devuelve MongoDB (opcional)
Criterios de ordenación para especificar el orden de los documentos devueltos desde MongoDB (opcional)
Cuando todos los campos especificados en la consulta, proyección y ordenación están en el mismo índice, MongoDB devuelve resultados directamente desde el índice, también llamado consulta cubierta.
Importante
Orden de clasificación
Los criterios de ordenación deben coincidir o invertir el orden del índice.
Considere un índice en el campo name en orden ascendente (AZ) y age en orden descendente (9-0):
name_1_age_-1
MongoDB utiliza este índice cuando ordena sus datos de cualquiera de las siguientes maneras:
nameascendente,agedescendentenamedescendente,ageascendente
Especificando un orden de clasificación de name y age ascendente o name y age descendente requiere una ordenación en memoria.
Para obtener más información sobre cómo garantizar que su índice cubra sus criterios de consulta y proyección, consulte los artículos del manual del servidor sobre cobertura de consultas.
Consideraciones operativas
Las siguientes pautas describen cómo puede optimizar la forma en que su aplicación utiliza los índices:
Para mejorar el rendimiento de las consultas, cree índices en los campos que aparecen con frecuencia en las consultas y operaciones de su aplicación que devuelven resultados ordenados.
Realice un seguimiento del índice de uso de la memoria y del disco para planificar la capacidad, porque cada índice que agrega consume espacio en disco y memoria cuando está activo.
Evite agregar índices que use con poca frecuencia. Tenga en cuenta que, cuando una operación de escritura actualiza un campo indexado, MongoDB actualiza el índice relacionado.
Dado que MongoDB admite esquemas dinámicos, las aplicaciones pueden realizar consultas sobre campos cuyos nombres no se pueden conocer con anticipación o son arbitrarios utilizando índices comodín. Los índices comodín no están diseñados para reemplazar la planificación de índices basada en la carga de trabajo.
Para obtener más información sobre cómo diseñar su modelo de datos y elegir índices apropiados para su aplicación, consulte la documentación del servidor MongoDB en Estrategias de indexación y Modelado de datos e índices.
Tipos de índice
MongoDB admite varios tipos de índices diferentes para admitir la consulta de sus datos. Las siguientes secciones describen los tipos de índice más comunes y proporcionan código de muestra para crear cada tipo de índice. Para ver una lista completa de los tipos de índices, consulta Índices en el manual del servidor.
Tip
El controlador Kotlin proporciona los índices Clase para crear y gestionar índices. Esta clase incluye métodos de fábrica estáticos para crear documentos de especificación de índices para diferentes tipos de claves de índice de MongoDB.
Los siguientes ejemplos utilizan el método createIndex() para crear varios índices y las siguientes clases de datos para modelar datos en MongoDB:
// Data class for the movies collection data class Movie( val title: String, val year: Int, val cast: List<String>, val genres: List<String>, val type: String, val rated: String, val plot: String, val fullplot: String, ) // Data class for the theaters collection data class Theater( val theaterId: Int, val location: Location ) { data class Location( val address: Address, val geo: Point ) { data class Address( val street1: String, val city: String, val state: String, val zipcode: String ) } }
Índices de campo único y compuestos
Índices de un solo campo
Los índices de campo único son índices que hacen referencia a un solo campo dentro de los documentos de una colección. Mejoran el rendimiento de las consultas y la ordenación de campos únicos, y son compatibles con los índices TTL, que eliminan automáticamente los documentos de una colección después de un tiempo determinado o en una hora específica.
Nota
El índice _id_ es un ejemplo de índice de campo único. Este índice se crea automáticamente en el campo _id al crear una nueva colección.
El siguiente ejemplo crea un índice en orden ascendente en el campo title:
val resultCreateIndex = moviesCollection.createIndex(Indexes.ascending(Movie::title.name)) println("Index created: $resultCreateIndex")
Index created: title_1
El siguiente es un ejemplo de una consulta que está cubierta por el índice creado en el fragmento de código anterior:
val filter = Filters.eq(Movie::title.name, "The Dark Knight") val sort = Sorts.ascending(Movie::title.name) val projection = Projections.fields( Projections.include(Movie::title.name), Projections.excludeId() ) data class Results(val title: String) val resultsFlow = moviesCollection.find<Results>(filter).sort(sort).projection(projection) resultsFlow.collect { println(it) }
Consulta la sección del manual de servidor de MongoDB sobre índices de campo único para obtener más información.
Índices compuestos
Los índices compuestos contienen referencias a múltiples campos dentro de los documentos de una colección, lo que mejora el rendimiento de las consultas y la clasificación.
Tip
Lee más sobre índices compuestos, prefijos de índice y orden de clasificación aquí.
El siguiente ejemplo crea un índice compuesto en los campos type y rated:
val resultCreateIndex = moviesCollection.createIndex(Indexes.ascending(Movie::type.name, Movie::rated.name)) println("Index created: $resultCreateIndex")
Index created: type_1_rated_1
El siguiente es un ejemplo de una consulta que está cubierta por el índice creado en el fragmento de código anterior:
val filter = Filters.and( Filters.eq(Movie::type.name, "movie"), Filters.eq(Movie::rated.name, "G") ) val sort = Sorts.ascending(Movie::type.name, Movie::rated.name) val projection = Projections.fields( Projections.include(Movie::type.name, Movie::rated.name), Projections.excludeId() ) val resultsFlow = moviesCollection.find(filter).sort(sort).projection(projection) resultsFlow.collect { println(it) }
Consulte la sección del manual del servidor MongoDB sobre índices compuestos para obtener más información.
Índices multiclave (índices en campos de matriz)
Los índices multiclave mejoran el rendimiento de las consultas que especifican un campo con un índice que contiene un valor de matriz. Se puede definir un índice multiclave con la misma sintaxis que un índice de campo único o compuesto.
El siguiente ejemplo crea un índice compuesto de múltiples claves en los campos rated, genres (una matriz de cadenas) y title:
val resultCreateIndex = moviesCollection.createIndex(Indexes.ascending(Movie::rated.name, Movie::genres.name, Movie::title.name)) println("Index created: $resultCreateIndex")
Index created: rated_1_genres_1_title_1
El siguiente es un ejemplo de una consulta que está cubierta por el índice creado en el fragmento de código anterior:
val filter = Filters.and( Filters.eq(Movie::genres.name, "Animation"), Filters.eq(Movie::rated.name, "G") ) val sort = Sorts.ascending(Movie::title.name) val projection = Projections.fields( Projections.include(Movie::title.name, Movie::rated.name), Projections.excludeId() ) val resultsFlow = moviesCollection.find(filter).sort(sort).projection(projection) resultsFlow.collect { println(it) }
Los índices multiclave se comportan de forma diferente a otros índices en cuanto a la cobertura de consultas, el cálculo de los límites de índice y el comportamiento de ordenación. Para obtener más información sobre los índices multiclave, incluyendo una explicación de su comportamiento y limitaciones, consulte Índices multiclave en el manual del servidor.
Índices de búsqueda de Atlas
La función de búsqueda en Atlas permite realizar búsquedas de texto completo en colecciones alojadas en MongoDB Atlas. Los índices especifican cómo realizar búsquedas de texto completo en campos específicos.
Para obtener más información sobre MongoDB Atlas Search, consulte la documentación de Índices de búsqueda de Atlas.
Puede llamar a los siguientes métodos en una colección para administrar sus índices de Atlas Search:
createSearchIndex()createSearchIndexes()listSearchIndexes()updateSearchIndex()dropSearchIndex()
Nota
Los métodos de gestión de índices de Atlas Search se ejecutan de forma asíncrona. Los métodos del controlador pueden regresar antes de confirmar su correcta ejecución. Para determinar el estado actual de los índices, llame al método listSearchIndexes().
Las siguientes secciones proporcionan ejemplos de código que demuestran cómo utilizar cada uno de los métodos anteriores.
Crear un índice de búsqueda
Puedes utilizar los métodos createSearchIndex() y createSearchIndexes() para crear índices de Atlas Search en una colección.
El siguiente ejemplo de código muestra cómo crear un índice único:
val index = Document( "mappings", Document("dynamic", true) ) val resultCreateIndex = moviesCollection.createSearchIndex("myIndex", index)
El siguiente ejemplo de código muestra cómo crear múltiples índices:
val indexOne = SearchIndexModel( "myIndex1", Document("analyzer", "lucene.standard").append( "mappings", Document("dynamic", true) ) ) val indexTwo = SearchIndexModel( "myIndex2", Document("analyzer", "lucene.simple").append( "mappings", Document("dynamic", true) ) ) val resultCreateIndexes = moviesCollection .createSearchIndexes(listOf(indexOne, indexTwo))
Índices de búsqueda de listas
Puede utilizar el método listSearchIndexes() para devolver una lista de los índices de búsqueda de Atlas en una colección.
El siguiente ejemplo de código muestra cómo imprimir una lista de los índices de búsqueda en una colección:
val searchIndexesList = moviesCollection.listSearchIndexes().toList()
Actualizar un índice de búsqueda
Puede utilizar el método updateSearchIndex() para actualizar un índice de Atlas Search.
El siguiente código muestra cómo actualizar un índice de búsqueda:
moviesCollection.updateSearchIndex( "myIndex", Document("analyzer", "lucene.simple").append( "mappings", Document("dynamic", false) .append( "fields", Document( "title", Document("type", "string") ) ) ) )
Eliminar un índice de búsqueda
Puede utilizar el método dropSearchIndex() para eliminar un índice de búsqueda de Atlas.
El siguiente código muestra cómo eliminar un índice de búsqueda de una colección:
moviesCollection.dropSearchIndex("myIndex");
Text Indexes
Los índices de texto permiten realizar búsquedas de texto en cadenas. Estos índices pueden incluir cualquier campo cuyo valor sea una cadena o un array de elementos de cadena. MongoDB admite la búsqueda de texto en varios idiomas. Puede especificar el idioma predeterminado al crear el índice.
Tip
MongoDB ofrece una solución mejorada de búsqueda de texto completo: Atlas Search. Para obtener más información sobre los índices de Atlas Search y cómo usarlos, consulte la sección "Índices de Atlas Search" de esta guía.
Campo único
El siguiente ejemplo crea un índice de texto en el campo plot:
try { val resultCreateIndex = moviesCollection.createIndex(Indexes.text(Movie::plot.name)) println("Index created: $resultCreateIndex") } catch (e: MongoCommandException) { if (e.errorCodeName == "IndexOptionsConflict") { println("there's an existing text index with different options") } }
Index created: plot_text
El siguiente es un ejemplo de una query cubierto por el índice creado en el snippet de código anterior. Ten en cuenta que se omite el sort porque los índices de texto no contienen orden de clasificación.
val filter = Filters.text("Batman") val projection = Projections.fields( Projections.include(Movie::fullplot.name), Projections.excludeId() ) data class Results(val fullplot: String) val resultsFlow = moviesCollection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Campos múltiples
Una colección solo puede contener un índice de texto. Si desea crear un índice de texto para varios campos de texto, debe crear un índice compuesto. Se ejecuta una búsqueda de texto en todos los campos de texto dentro del índice compuesto.
El siguiente fragmento crea un índice de texto compuesto para los campos title y genre:
try { val resultCreateIndex = moviesCollection.createIndex( Indexes.compoundIndex( Indexes.text(Movie::title.name), Indexes.text(Movie::genres.name) ) ) println("Index created: $resultCreateIndex") } catch (e: MongoCommandException) { if (e.errorCodeName == "IndexOptionsConflict") { println("there's an existing text index with different options") } }
Index created: title_text_genre_text
Para obtener más información, consulte las siguientes entradas del Manual del servidor:
Índices geoespaciales
MongoDB admite consultas de datos de coordenadas geoespaciales mediante 2índices dsphere. Con un 2dsphere índice, puede consultar los datos geoespaciales por inclusión, intersección y proximidad. Para obtener más información sobre la consulta de datos geoespaciales, consulte Consultas geoespaciales en el manual del servidor.
Para crear un 2dsphere índice, debe especificar un campo que contenga únicamente objetos GeoJSON. Para obtener más información sobre este tipo, consulte Objetos GeoJSON en el manual del servidor.
El campo location.geo en el siguiente documento de muestra de la colección theaters en la base de datos sample_mflix es un objeto Punto GeoJSON que describe las coordenadas del teatro:
{ "_id" : ObjectId("59a47286cfa9a3a73e51e75c"), "theaterId" : 104, "location" : { "address" : { "street1" : "5000 W 147th St", "city" : "Hawthorne", "state" : "CA", "zipcode" : "90250" }, "geo" : { "type" : "Point", "coordinates" : [ -118.36559, 33.897167 ] } } }
El siguiente ejemplo crea un índice 2dsphere en el campo location.geo:
val resultCreateIndex = theatersCollection.createIndex( Indexes.geo2dsphere("${Theater::location.name}.${Theater.Location::geo.name}") ) println("Index created: $resultCreateIndex")
Index created: location.geo_2dsphere
Importante
Intentar crear un índice geoespacial en un campo que ya está cubierto por un índice geoespacial genera un error.
El siguiente es un ejemplo de una consulta geoespacial que está cubierta por el índice creado en el fragmento de código anterior:
// MongoDB Headquarters in New York, NY. val refPoint = Point(Position(-73.98456, 40.7612)) val filter = Filters.near( "${Theater::location.name}.${Theater.Location::geo.name}", refPoint, 1000.0, 0.0 ) val resultsFlow = theatersCollection.find(filter) resultsFlow.collect { println(it) }
MongoDB también admite 2d índices para calcular distancias en un plano euclidiano. Para obtener más información, consulte Consultas geoespaciales en el manual del servidor.
Unique Indexes
Los índices únicos garantizan que los campos indexados no almacenen valores duplicados. De forma predeterminada, MongoDB crea un índice único en el campo _id durante la creación de una colección. Para crear un índice único, especifique el campo o la combinación de campos que desea evitar la duplicación y configure la opción unique como true.
El siguiente ejemplo crea un índice descendente único en el campo theaterId:
try { val indexOptions = IndexOptions().unique(true) val resultCreateIndex = theatersCollection.createIndex( Indexes.descending(Theater::theaterId.name), indexOptions ) println("Index created: $resultCreateIndex") } catch (e: DuplicateKeyException) { println("duplicate field values encountered, couldn't create index: \t${e.message}") }
Index created: theaterId_-1
Importante
Si realiza una operación de escritura que almacena un valor duplicado que viola el índice único, el controlador genera un DuplicateKeyException y MongoDB arroja un error similar al siguiente:
E11000 duplicate key error index
Consulte la página Índices únicos en el manual del servidor MongoDB para obtener más información.
Índices agrupados
Los índices agrupados indican a una colección que almacene documentos ordenados por un valor de clave. Para crear un índice agrupado, especifique la opción de índice agrupado con el _id campo como clave y el campo único al true crear la colección.
El siguiente ejemplo crea un índice agrupado en el campo _id de la colección vendors:
val clusteredIndexOptions = ClusteredIndexOptions(Document("_id", 1), true) val createCollectionOptions = CreateCollectionOptions().clusteredIndexOptions(clusteredIndexOptions) database.createCollection("vendors", createCollectionOptions)
Consulte las secciones del manual del servidor MongoDB para obtener más información:
Eliminar un índice
Puede eliminar cualquier índice no utilizado excepto el índice único predeterminado en el campo _id.
Las siguientes secciones muestran las formas de remover índices:
Uso de un documento de especificación de índice
Uso de un campo de nombre indexado
Usando un carácter comodín para eliminar todos los índices
Eliminar un índice mediante un documento de especificación de índice
Pase un documento de especificación del índice al método dropIndex() para remover un índice de una colección. Un documento de especificación del índice es una instancia de Bson que especifica el tipo de índice en un campo determinado.
El siguiente fragmento elimina un índice ascendente en el campo title de una colección:
moviesCollection.dropIndex(Indexes.ascending(Movie::title.name));
Importante
Si desea eliminar un índice de texto, debe usar su nombre. Consulte la sección "Eliminar un índice mediante un campo de nombre" para obtener más información.
Eliminar un índice mediante un campo de nombre
Pase el campo name del índice al método dropIndex() para eliminar un índice de una colección.
Si necesita encontrar el nombre de su índice, utilice el método listIndexes() para ver el valor de los campos name en sus índices.
El siguiente fragmento recupera e imprime todos los índices de una colección:
val indexes = moviesCollection.listIndexes() indexes.collect { println(it.toJson()) }
Si llama a listIndex() en una colección que contiene un índice de texto, la salida podría parecerse a la siguiente:
{ "v": 2, "key": {"_id": 1}, "name": "_id_" } { "v": 2, "key": {"_fts": "text", "_ftsx": 1}, "name": "title_text", "weights": {"title": 1}, "default_language": "english", "language_override": "language", "textIndexVersion": 3 }
Esta salida nos dice que los nombres de los índices existentes son "_id" y "title_text".
El siguiente fragmento elimina el índice "title_text" de la colección:
moviesCollection.dropIndex("title_text")
Nota
No se puede eliminar un solo campo de un índice de texto compuesto. Debe eliminar todo el índice y crear uno nuevo para actualizar los campos indexados.
Eliminar un índice usando un carácter comodín
Puede eliminar todos los índices llamando al método dropIndexes() en su colección:
moviesCollection.dropIndexes()
Para versiones anteriores de MongoDB, pase "*" como parámetro a su llamada a dropIndex() en su colección:
moviesCollection.dropIndex("*")
Para obtener más información sobre los métodos de esta sección, consulte la siguiente Documentación de la API: