Docs Menu
Docs Home
/ /
Propiedades

Índices parciales

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.

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: value o utilizando el $eq operador),

  • $exists: true expresión,

  • $gt, $gte, $lt, $lte expressions,

  • $type expresiones,

  • $and operador,

  • $or operador,

  • $in operador

Por ejemplo, la siguiente operación crea un índice compuesto que indexa solo los documentos con un campo rating mayor que 5.

db.restaurants.createIndex(
{ cuisine: 1, name: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)

Puedes especificar una opción partialFilterExpression para todos los tipos de índices de MongoDB.

Tip

Para aprender a gestionar índices en MongoDB Compass, consulte Gestionar índices.

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.restaurants.createIndex(
{ cuisine: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)

La siguiente query puede usar el índice ya que el predicado de la query incluye la condición rating: { $gte: 8 } que coincide con un subconjunto de documentos coincidentes con la expresión del filtro de índice rating: { $gt: 5 }:

db.restaurants.find( { cuisine: "Italian", rating: { $gte: 8 } } )

Sin embargo, la siguiente query no puede utilizar el índice parcial en el campo cuisine porque el uso del índice da como resultado un conjunto de resultados incompleto. Específicamente, el predicado de query incluye la condición rating: { $lt: 8 } mientras que el índice tiene el filtro rating: { $gt: 5 }. Es decir, la query { cuisine: "Italian", rating: { $lt: 8 } } coincide con más documentos (p. ej., un restaurante italiano con una calificación igual a 1) de los que están indexados.

db.restaurants.find( { cuisine: "Italian", rating: { $lt: 8 } } )

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.restaurants.find( { cuisine: "Italian" } )

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.contacts.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.contacts.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.contacts.find( { name: "xyz", email: { $regex: /\.org$/ } } )

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.contacts.find( { name: "xyz", email: { $exists: false } } )

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.

  • No puedes especificar tanto la opción partialFilterExpression como la opción sparse.

  • _id los í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 partialFilterExpression no puede hacer referencia a un campo cifrado.

Considera una colección restaurants que contiene documentos que se asemejan al siguiente ejemplo:

db.restaurants.insertOne(
{
_id: ObjectId("5641f6a7522545bc535b5dc9"),
address: {
building: "1007",
coord: [
-73.856077,
40.848447
],
street: "Morris Park Ave",
zipcode: "10462"
},
borough: "Bronx",
cuisine: "Bakery",
rating: {
date: ISODate("2014-03-03T00:00:00Z"),
grade: "A",
score: 2
},
name: "Morris Park Bake Shop",
restaurant_id: "30075445"
}
)

Podrías añadir un índice parcial en los campos borough y cuisine al elegir solo indexar documentos donde el campo rating.grade sea A:

db.restaurants.createIndex(
{ borough: 1, cuisine: 1 },
{ partialFilterExpression: { 'rating.grade': { $eq: "A" } } }
)

A continuación, la siguiente query sobre la colección restaurants usa el índice parcial para devolver los restaurantes en el Bronx con rating.grade igual a A:

db.restaurants.find( { borough: "Bronx", 'rating.grade': "A" } )

Sin embargo, la siguiente consulta no puede utilizar el índice parcial porque la expresión de consulta no incluye el campo rating.grade:

db.restaurants.find( { borough: "Bronx", cuisine: "Bakery" } )

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.

Por ejemplo, una colección users contiene los siguientes documentos:

db.users.insertMany( [
{ _id: ObjectId("56424f1efa0358a27fa1f99a"), username: "david", age: 29 },
{ _id: ObjectId("56424f37fa0358a27fa1f99b"), username: "amanda", age: 35 },
{ _id: ObjectId("56424fe2fa0358a27fa1f99c"), username: "rajiv", age: 57 }
] )

La siguiente operación crea un índice que especifica una restricción única en el campo username y una expresión de filtro parcial age: { $gte: 21 }.

db.users.createIndex(
{ username: 1 },
{ unique: true, partialFilterExpression: { age: { $gte: 21 } } }
)

El índice impide la inserción de los siguientes documentos ya que existen documentos con los nombres de usuario especificados y los campos age son mayores que 21:

db.users.insertMany( [
{ username: "david", age: 27 },
{ username: "amanda", age: 25 },
{ username: "rajiv", age: 32 }
] )

Sin embargo, se permiten los siguientes documentos con nombres de usuario duplicados, ya que la restricción de unicidad solo se aplica a los documentos con age mayor o igual a 21.

db.users.insertMany( [
{ username: "david", age: 20 },
{ username: "amanda" },
{ username: "rajiv", age: null }
] )

Volver

Convertir a único

En esta página