Los índices parciales solo indexan los documentos de una colección que cumplen con una expresión de filtro especificada. Al indexar un subconjunto de los documentos en una colección, los índices parciales requieren menos almacenamiento y reducen los costos de rendimiento para la creación y el mantenimiento de índices.
Crear un índice parcial
Para crear una partial índice, utilice el
db.collection.createIndex() Método con la partialFilterExpression opción. La partialFilterExpression opción acepta un documento que especifica la condición de filtro mediante:
expresiones de igualdad (es decir,
field: valueo con el operador$eq)$exists: trueexpresión$typeexpresiones$andoperador$oroperador$inoperador$geoWithinoperador$geoIntersectsoperador
Por ejemplo, la siguiente operación crea un índice compuesto que indexa solo los documentos donde el campo genre es Drama:
db.movies.createIndex( { title: 1 }, { partialFilterExpression: { genres: "Drama" } } )
Puedes especificar una opción partialFilterExpression para todos los tipos de índicesde MongoDB. Al especificar un partialFilterExpression para un índice TTL en una colección de series de tiempo, solo puedes filtrar en la colección metaField.
Tip
Para aprender a gestionar índices en MongoDB Compass, consulte Gestionar índices.
Comportamiento
Cobertura de la query
MongoDB no usará el índice parcial para una operación de query o clasificación si el uso del índice da como resultado un conjunto de resultados incompleto.
Para usar el índice parcial, una query debe contener la expresión de filtro (o una expresión de filtro modificada que especifique un subconjunto de la expresión de filtro) como parte de su condición de query.
Por ejemplo, dado el siguiente índice:
db.users.createIndex( { name: 1 }, { partialFilterExpression: { password: { $exists: true } } } )
La siguiente consulta puede utilizar el índice ya que el predicado de la consulta incluye la condición password: { $exists: true } que coincide con los documentos que coinciden con la expresión de filtro de índice password: { $exists: true
}:
db.users.find( { name: "Ned Stark", password: { $exists: true } } )
Sin embargo, la siguiente consulta no puede usar el índice parcial en el campo name porque al usar el índice se obtiene un conjunto de resultados incompleto. En concreto, el predicado de la consulta incluye la condición password: { $exists: false }, mientras que el índice tiene el filtro password: { $exists:
true }. Es decir, la consulta { name: "Ned Stark", password: { $exists: false }
} coincide con más documentos (usuarios sin contraseña) de los que abarca el índice.
db.users.find( { name: "Ned Stark", password: { $exists: false } } )
De manera similar, la siguiente query no puede usar el índice parcial porque el predicado de la query no incluye la expresión del filtro y usar el índice devolvería un conjunto de resultados incompleto.
db.users.find( { name: "Ned Stark" } )
Comparación con índices escasos
Usa índices parciales en lugar de índices dispersos si deseas un control más preciso sobre qué documentos indexar:
Los índices dispersos incluyen o excluyen documentos únicamente basándose en la existencia del campo indexado (o de múltiples campos, en el caso de índices compuestos dispersos).
Los índices parciales incluyen o no documentos según la expresión del filtro. La expresión puede incluir campos además de las claves de índice y puede especificar condiciones distintas a la existencia de un campo.
Por ejemplo, un índice parcial puede implementar el mismo comportamiento que un índice disperso. Este índice parcial admite las mismas queries que un índice disperso en el campo name:
db.users.createIndex( { name: 1 }, { partialFilterExpression: { name: { $exists: true } } } )
Sin embargo, un índice parcial también puede filtrar en campos distintos de la clave del índice. Por ejemplo, un índice parcial en el campo name puede verificar la existencia del campo email:
db.users.createIndex( { name: 1 }, { partialFilterExpression: { email: { $exists: true } } } )
Para que el optimizador de la query elija este índice parcial, el predicado de la consulta debe incluir una condición en el campo name así como una coincidencia no nula en el campo email.
Por ejemplo, la siguiente query puede utilizar el índice porque incluye tanto una condición en el campo name como una coincidencia no nula en el campo email
db.users.find( { name: "Ned Stark", email: { $regex: /gameofthron\.es$/ } } )
Sin embargo, la siguiente query no puede utilizar el índice porque incluye una coincidencia nula en el campo email, lo que no está permitido por la expresión de filtro { email: { $exists: true } }:
db.users.find( { name: "Ned Stark", email: { $exists: false } } )
Índices parciales de TTL
Los índices parciales también pueden ser índices TTL. Los índices TTL parciales coinciden con la expresión de filtro especificada y solo expiran esos documentos. Para obtener más detalles, consulta Expirar documentos con condiciones de filtro.
Restricciones
No puedes especificar tanto la opción
partialFilterExpressioncomo la opciónsparse._idlos índices no pueden ser índices parciales.Los índices de clave de partición no pueden ser índices parciales.
Si estás utilizando cifrado a nivel de campo del lado del cliente o Queryable Encryption, un
partialFilterExpressionno puede hacer referencia a un campo cifrado.
Índices equivalentes
A partir de MongoDB 7.3, no podrá crear índices equivalentes, que son índices parciales con las mismas claves de índice y las mismas expresiones parciales que utilizan una intercalación.
Para bases de datos en MongoDB 7.3 con índices equivalentes existentes, los índices se conservan, pero solo se utiliza el primer índice equivalente en las queries. Este es el mismo comportamiento que las versiones de MongoDB anteriores a 7.3.
Por ejemplo, no se pueden crear dos índices que solo difieran en el caso del texto en la expresión de filtro parcial.
Ejemplos
Los ejemplos de esta página utilizan datos de Conjunto de datos de muestra sample_mflix. Para obtener más información sobre cómo cargar este conjunto de datos en su implementación de MongoDB autogestionada, consulte Cargar el conjunto de datos de muestra. Si realizó alguna modificación en las bases de datos de muestra, es posible que deba eliminarlas y volver a crearlas para ejecutar los ejemplos de esta página.
Cree un índice parcial en una colección
El siguiente ejemplo agrega un índice parcial en los campos title y genres. La operación solo indexa documentos donde el campo rating es PG:
db.movies.createIndex( { title: 1, genres: 1 }, { partialFilterExpression: { rated: "PG" } } )
La siguiente consulta en la colección movies utiliza el índice parcial para devolver los escritores de todas las películas tituladas "Los tres mosqueteros":
db.movies.find( { title: "The Three Musketeers", genres: ["Action", "Adventure", "Comedy"], rated: "PG" }, { writers: 1 } )
Sin embargo, la siguiente consulta no puede utilizar el índice parcial porque el predicado de la consulta no incluye el filtro rating:
db.movies.find( { genres: "Drama" }, { title: 1 } ).limit(5)
Índice parcial con restricción de unicidad
Los índices parciales solo indexan los documentos de una colección que cumplen con una expresión de filtro especificada. Si especificas tanto el partialFilterExpression como una restricción única, la restricción única solo se aplica a los documentos que cumplen con la expresión de filtro. Un índice parcial con una restricción de unicidad no impide la inserción de documentos que no cumplan dicha restricción si estos no cumplen con los criterios de filtrado.
La siguiente operación en la users colección crea un índice que especifica una restricción única en el email campo y una expresión de filtro password: { $exists: true } parcial.
db.users.createIndex( { name: 1 }, { name: "name_partial_unique_idx", unique: true, partialFilterExpression: { password: { $exists: true } } } )
El índice impide la inserción de los documentos que tienen tanto una dirección de correo electrónico que ya existe en la colección como un campo password ya existente.
Sin embargo, se permiten los siguientes documentos con direcciones de correo electrónico duplicadas, ya que la restricción única solo se aplica a los documentos con un campo password.
db.users.insertMany( [ // This document does NOT have a password field, so it's NOT indexed // The unique constraint does not apply to it { name: "Jon Snow", email: "jon1@example.com" }, // This document has a password field, so it IS indexed // The unique constraint applies to it { name: "Sansa Stark", email: "sansa@example.com", password: "password123" }, // This document does NOT have a password field, so it's NOT indexed // We can insert it even though it has the same name as the first document // This demonstrates that the unique constraint only applies to indexed documents { name: "Jon Snow", email: "jon2@example.com" } ] )