Docs Menu
Docs Home
/ /
Propiedades

Índices parciales

Nuevo en la versión 3.2.

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 solo en el nivel superior

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.

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" } )

Se recomiendan los índices parciales en lugar de los dispersos. Estos últimos ofrecen las siguientes ventajas:

  • Mayor control sobre qué documentos se indexan.

  • Un superconjunto de la funcionalidad ofrecida por los índices dispersos.

Los índices dispersos seleccionan documentos para indexar únicamente en función de la existencia del campo indexado o, para índices compuestos, en función de la existencia de los campos indexados.

Los índices parciales determinan las entradas del índice según el filtro especificado. El filtro puede incluir campos distintos a las claves del índice y especificar condiciones distintas a la simple comprobación de existencia. Por ejemplo, un índice parcial puede implementar el mismo comportamiento que un índice disperso:

db.contacts.createIndex(
{ name: 1 },
{ partialFilterExpression: { name: { $exists: true } } }
)

Este índice parcial admite las mismas consultas que un índice disperso en el campo name.

Sin embargo, un índice parcial también puede especificar expresiones de filtro en campos distintos de la clave del índice. Por ejemplo, la siguiente operación crea un índice parcial, donde el índice está en el campo name, pero la expresión de filtro está en el 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.

A partir de MongoDB,5.0 se pueden crear múltiples índices parciales utilizando el mismo patrón de clave siempre que los campos partialFilterExpression no expresen filtros equivalentes.

En versiones anteriores de MongoDB, no se permitía la creación de múltiples índices parciales cuando se usaba el mismo patrón de clave con diferentes partialFilterExpressions.

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.

Considere una colección restaurants que contiene documentos que se parecen a los siguientes

{
"_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:

{ "_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

Unique Indexes

En esta página