Los índices dispersos en MongoDB difieren de a nivel de bloque índices dispersos en otras bases de datos. Los índices escasos solo contienen entradas para document que tienen el campo indexado, incluso si el campo del índice contiene un valor nulo. El índice se salta cualquier document que carezca del campo indexado. El índice es "escaso" porque no incluye todos los document de una colección. Por el contrario, los índices no dispersos contienen todos los documentos de una colección, almacenando valores nulos para aquellos documentos que no contienen el campo indexado.
Importante
Los índices parciales pueden funcionar como índices dispersos, pero también admiten expresiones de filtro para condiciones más allá de si un campo existe. Utiliza un índice parcial para obtener un mayor control si necesitas un filtro exacto.
Crear un índice disperso
Para crear un índice disperso, utiliza la db.collection.createIndex() método con la opción sparse configurada a true.
Por ejemplo, la siguiente operación en mongosh crea un índice disperso en el campo plot de la colección movies:
db.movies.createIndex( { "plot": 1 }, { sparse: true } )
El índice no indexa documentos que no incluyen el campo plot.
Comportamiento
Índice disperso y resultados incompletos
Si un índice disperso resultase en un conjunto de resultados incompleto para consultas y operaciones de clasificación, MongoDB no usará ese índice a menos que un hint() especifique explícitamente el índice. Consulte Un índice disperso en una colección no puede devolver resultados completos para ver un ejemplo.
Si incluye un hint() que especifica un índice disperso cuando realiza un count() de todos los documentos en una colección (es decir, con un predicado de query vacío), se utiliza el índice disperso incluso si da como resultado un conteo incorrecto.
Por ejemplo, crear un índice disperso en el campo rated de la colección movies .
db.movies.createIndex( { rated: 1 }, { sparse: true } )
Si cuentas el número de documentos en la colección movies e incluyes una sugerencia que especifique ese índice disperso, la operación devuelve únicamente los documentos que contienen el campo rated.
db.movies.countDocuments( {}, { hint: { rated: 1 } } )
Para obtener el recuento correcto del número de documentos en la colección movies, no hint() con un índice disperso al realizar un recuento de todos los documentos en una colección.
db.movies.countDocuments()
Índices que son escasos por defecto
Los siguientes tipos de índices siempre son dispersos:
Índices compuestos dispersos
Los índices compuestos pueden contener diferentes tipos de índices dispersos. La combinación de tipos de índice determina cómo el índice compuesto coincide con los documentos.
Esta tabla resume el comportamiento de un índice compuesto que incluye diferentes tipos de índices escasos:
Componentes del índice compuesto | Comportamiento del índice compuesto |
|---|---|
Ascending indexes Descending indexes | Solo indexa documentos que contengan un valor para, al menos, una de las claves. |
Solo indexa un documento cuando este contiene un valor para uno de los campos | |
Solo indexa un documento cuando coincide con uno de los campos |
Propiedades dispersas y únicas
Un índice que es tanto disperso como único impide que una colección tenga documentos con valores duplicados para un campo, pero permite múltiples documentos que omiten la clave.
Ejemplos
Crea un índice disperso en una colección
El siguiente ejemplo crea un índice disperso en el campo password:
db.users.createIndex( { password: 1 } , { sparse: true } )
Luego, la siguiente query en la colección users utiliza el índice disperso para devolver los documentos que tienen el campo password:
db.users.find( { password: { $exists: true } } ).sort({ password: 1 }).limit(5)
Si un document no contiene el campo password, la query no devuelve ese document.
Un índice disperso en una colección no puede devolver resultados completos
Considera la colección movies donde algunos documentos no tienen un campo plot.
El siguiente ejemplo crea un índice disperso en el campo plot:
db.movies.createIndex( { "plot": 1 }, { sparse: true } )
Considera el siguiente query para devolver todos los documentos de la colección movies, ordenados por el campo plot:
db.movies.find().sort( { plot: -1 } )
Aunque la clasificación se realiza por el campo indexado, si algunos documentos de la colección movies no tienen un campo plot, MongoDB no selecciona el índice disperso para cumplir con la query y devolver resultados completos.
Para usar el índice disperso, especifica explícitamente el índice con hint():
db.movies.find().sort( { plot: -1 } ).hint( { plot: 1 } ).limit(5)
Esta consulta solo devuelve documentos en la colección movies que contienen el campo plot.
Índice disperso con restricción de unicidad
La siguiente operación crea un índice con una restricción única y un filtro disperso en el campo password en el users:
db.users.createIndex( { password: 1 } , { sparse: true, unique: true } )
Este índice permite insertar documentos que tengan valores únicos para el campo password, o que no incluyan un campo password. Para los document de ejemplo en la colección users, el índice permite las siguientes operaciones de inserción:
db.users.insertMany( [ { "name": "Jon Snow", "email": "jon@gameofthron.es", "password": "$2b$12$newHashedPassword1234567890ABC" }, { "name": "Sansa Stark", "email": "sansa@gameofthron.es", "password": "$2b$12$anotherNewPassword1234567890DEF" }, { "name": "Bran Stark", "email": "bran@gameofthron.es" } ] )
Sin embargo, el índice no permite insertar document que contengan direcciones de correo electrónico que ya existan en la colección.
Índices únicos escasos y no escasos
A partir de MongoDB 5.0, los índices dispersos únicos y los índices no dispersos únicos con el mismo patrón de clave pueden existir en una sola colección.
Creación de índices únicos y dispersos
Este ejemplo crea múltiples índices con el mismo patrón de clave y diferentes opciones de sparse:
db.users.createIndex( { password : 1 }, { name: "unique_index", unique: true } )
db.users.createIndex( { password : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )
Creación de índices básicos y dispersos
También se pueden crear índices básicos con el mismo patrón de claves con y sin la opción de dispersión:
db.users.createIndex( { password : 1 }, { name: "sparse_index", sparse: true } )
db.users.createIndex( { password : 1 }, { name: "basic_index" } )