Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ /

Índices Parciais

Nesta página

  • Criar um índice parcial
  • Comportamento
  • Restrições
  • Exemplos

Os índices parciais indexam apenas os documentos em uma collection que atendem a uma expressão de filtro especificada. Ao indexar um subconjunto de documentos em uma collection, os índices parciais têm requisitos de armazenamento mais baixos e custos de desempenho reduzidos para criação e manutenção de índices.

Para criar um índice partial, use o método db.collection.createIndex() com a opção partialFilterExpression. A opção partialFilterExpression aceita um documento que especifica a condição do filtro usando:

  • expressões de igualdade (ou seja, field: value ou usando o operador $eq),

  • $exists: true expressão,

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

  • $type expressões,

  • $and operador,

  • $or operador,

  • $in operador, operador

Por exemplo, a seguinte operação cria um índice composto que indexa somente os documentos com um campo rating maior que 5.

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

Você pode especificar uma opção partialFilterExpression para todos os tipos de índices do MongoDB. Ao especificar um partialFilterExpression para um índice TTL em uma coleção de séries temporais, você só pode filtrar na coleção metaField.

Dica

Veja também:

Para saber como gerenciar índices no MongoDB Compass, consulte Gerenciar índices.

O MongoDB não utiliza o índice parcial para uma query ou operação de classificação se utilizar os resultados do índice em um conjunto de resultados incompleto.

Para usar o índice parcial, uma query deve conter a expressão de filtro (ou uma expressão de filtro modificada que especifica um subconjunto da expressão de filtro) como parte de sua condição.

Por exemplo, considerando o índice a seguir:

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

A query a seguir pode usar o índice, pois seu predicado inclui a condição rating: { $gte: 8 } que corresponde a um subconjunto de documentos correspondentes à expressão de filtrorating: { $gt: 5 } do índice:

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

No entanto, a query a seguir não pode usar o índice parcial no campo cuisine porque o uso do índice resulta em um conjunto de resultados incompleto. Especificamente, o predicado da query inclui a condição rating: { $lt: 8 }, enquanto o índice tem o filtro rating: { $gt: 5 }. Ou seja, a query { cuisine: "Italian", rating: { $lt: 8 } } corresponde a mais documentos (por exemplo, um restaurante italiano com uma classificação igual a 1) do que os indexados.

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

Da mesma forma, a query a seguir não pode usar o índice parcial porque o predicado da query não inclui a expressão de filtro e o uso do índice retornaria um conjunto de resultados incompleto.

db.restaurants.find( { cuisine: "Italian" } )

Os índices parciais são preferidos em relação aos índices esparsos. Os índices parciais fornecem os seguintes benefícios:

  • Maior controle de quais documentos são indexados.

  • Um superconjunto da funcionalidade oferecida pelos índices esparsos.

Índices esparsos selecionam documentos para indexar somente com base na existência do campo indexado ou, para índices compostos, na existência dos campos indexados.

Os índices parciais determinam as entradas de índice com base no filtro especificado. O filtro pode incluir campos diferentes das chaves de índice e pode especificar condições diferentes de apenas uma verificação de existência. Por exemplo, um índice parcial pode implementar o mesmo comportamento de um índice esparso:

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

Este índice parcial suporta as mesmas queries que um índice esparso no campo name.

No entanto, um índice parcial também pode especificar expressões de filtro em campos diferentes da chave de índice. Por exemplo, a seguinte operação cria um índice parcial, no qual o índice está no campo name, mas a expressão de filtro está no campo email :

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

Para que o otimizador de queries escolha esse índice parcial, o predicado da query deve incluir uma condição no campo name, bem como uma correspondência não nula no campo email.

Por exemplo, a query a seguir pode usar o índice porque inclui uma condição no campo name e uma correspondência não nula no campo email:

db.contacts.find( { name: "xyz", email: { $regex: /\.org$/ } } )

No entanto, a query a seguir não pode usar o índice porque inclui uma correspondência nula no campo email, o que não é permitido pela expressão de filtro { email: { $exists: true } }:

db.contacts.find( { name: "xyz", email: { $exists: false } } )

Os índices parciais também podem ser índices TTL. Os índices TTL parciais correspondem à expressão do filtro especificada e expiram apenas esses documentos. Para obter detalhes, consulte Expirar documentos com condições de filtro.

  • Você não pode especificar a opção partialFilterExpression e a opção sparse.

  • _id os índices não podem ser índices parciais.

  • Os índices de chave de shard não podem ser índices parciais.

  • Se você estiver utilizando o Client-Side Field Level Encryption ou o Queryable Encryption, um partialFilterExpression não poderá fazer referência a um campo criptografado.

A partir do MongoDB 7.3, não é possível criar índices equivalentes, que são índices parciais com as mesmas chaves de índice e as mesmas expressões parciais que usam um agrupamento.

Para bancos de dados no MongoDB 7.3 com índices equivalentes existentes, os índices são retidos, mas somente o primeiro índice equivalente é usado nas consultas. Esse é o mesmo comportamento das versões MongoDB anteriores a 7.3.

Para obter um exemplo, consulte Exemplo de índices equivalentes.

Considere uma collection restaurants contendo documentos que se assemelham ao seguinte

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

Você pode adicionar um índice parcial nos campos borough e cuisine escolhendo somente para indexar documentos onde o campo rating.grade é A:

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

Em seguida, a seguinte query na collection restaurants utiliza o índice parcial para retornar os restaurantes no Bronx com rating.grade igual a A:

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

No entanto, a query a seguir não pode usar o índice parcial porque o predicado da query não inclui o campo rating.grade :

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

Os índices parciais indexam apenas os documentos em uma collection que atendem a uma expressão de filtro especificada. Se você especificar a partialFilterExpression e uma restrição exclusiva, esta só se aplicará aos documentos que atenderem à expressão de filtro. Um índice parcial com uma restrição exclusiva não impede a inserção de documentos que não atendem à restrição exclusiva se os documentos não atenderem aos critérios do filtro.

Por exemplo, uma collection users contém os seguintes documentos:

{ "_id" : ObjectId("56424f1efa0358a27fa1f99a"), "username" : "david", "age" : 29 }
{ "_id" : ObjectId("56424f37fa0358a27fa1f99b"), "username" : "amanda", "age" : 35 }
{ "_id" : ObjectId("56424fe2fa0358a27fa1f99c"), "username" : "rajiv", "age" : 57 }

A seguinte operação cria um índice que especifica uma restrição exclusiva no campo username e uma expressão de filtro parcial age: { $gte: 21 }.

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

O índice impede a inserção dos seguintes documentos, pois já existem documentos com os nomes de usuário especificados e os campos age são maiores que 21:

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

No entanto, os seguintes documentos com nomes de usuário duplicados são permitidos, pois a restrição exclusiva só se aplica a documentos com age maior ou igual a 21.

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

A partir do MongoDB 7.3, não é possível criar índices equivalentes, que são índices parciais com as mesmas chaves de índice e as mesmas expressões parciais que usam um agrupamento.

Para bancos de dados no MongoDB 7.3 com índices equivalentes existentes, os índices são retidos, mas somente o primeiro índice equivalente é usado nas consultas. Esse é o mesmo comportamento das versões MongoDB anteriores a 7.3.

Nas versões anteriores do MongoDB , você pode criar dois índices equivalentes. O exemplo seguinte cria uma coleção pizzas e dois índices equivalentes denominados index0 e index1:

// Create the pizzas collection
db.pizzas.insertMany( [
{ _id: 0, type: "pepperoni", size: "small", price: 4 },
{ _id: 1, type: "cheese", size: "medium", price: 7 },
{ _id: 2, type: "vegan", size: "large", price: 8 }
] )
// Create two equivalent indexes with medium pizza sizes
db.pizzas.createIndex(
{ type: 1 },
{ name: "index0",
partialFilterExpression: { size: "medium" },
collation: { locale: "en_US", strength: 1 }
}
)
db.pizzas.createIndex(
{ type: 1 },
{ name: "index1",
partialFilterExpression: { size: "MEDIUM" },
collation: { locale: "en_US", strength: 1 }
}
)

Os índices são equivalentes porque os dois índices especificam o mesmo tamanho da pizza e diferem apenas nas maiúsculas e minúsculas do texto na expressão de filtro parcial . Somente um índice é usado pelas consultas: o índice que foi criado primeiro, que é index0 no exemplo anterior.

A partir do MongoDB 7.3, você não pode criar o segundo índice (index1) e este erro é retornado:

MongoServerError: Index already exists with a different name: index0

Nas versões MongoDB anteriores a 7.3, você pode criar os índices, mas somente o primeiro índice (index0) é usado com estas queries:

db.pizzas.find( { type: "cheese", size: "medium" } ).collation(
{ locale: "en_US", strength: 1 }
)
db.pizzas.find( { type: "cheese", size: "MEDIUM" } ).collation(
{ locale: "en_US", strength: 1 }
)
db.pizzas.find( { type: "cheese", size: "Medium" } ).collation(
{ locale: "en_US", strength: 1 }
)

Voltar

Oculto