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.
Criar um índice parcial
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: valueou usando o operador$eq)$exists: trueexpressão$typeexpressões$andoperador, operador$oroperador, operador$inoperador, operador$geoWithinoperador, operador$geoIntersectsoperador, operador
Por exemplo, a seguinte operação cria um índice composto que indexa somente os documentos onde o campo genre é Drama:
db.movies.createIndex( { title: 1 }, { partialFilterExpression: { genres: "Drama" } } )
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
Para saber como gerenciar índices no MongoDB Compass, consulte Gerenciar índices.
Comportamento
Cobertura de query
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.users.createIndex( { name: 1 }, { partialFilterExpression: { password: { $exists: true } } } )
A query a seguir pode usar o índice, pois seu predicado inclui a condição password: { $exists: true } que corresponde a documentos correspondentes à expressão de filtro password: { $exists: true
} do índice:
db.users.find( { name: "Ned Stark", password: { $exists: true } } )
No entanto, a query a seguir não pode usar o índice parcial no campo name porque o uso do índice resulta em um conjunto de resultados incompleto. Especificamente, o predicado da query inclui a condição password: { $exists: false }, enquanto o índice tem o filtro password: { $exists:
true }. Ou seja, a query { name: "Ned Stark", password: { $exists: false }
} corresponde a mais documentos (usuários sem senhas) do que o índice cobre.
db.users.find( { name: "Ned Stark", password: { $exists: false } } )
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.users.find( { name: "Ned Stark" } )
Comparação com índices esparsos
Use índices parciais em índices esparsos se desejar um controle mais preciso sobre quais documentos indexar:
Índices esparsos incluem ou excluem documentos somente com base na presença do campo indexado (ou de vários campos, para índices compostos esparsos).
Os índices parciais incluem ou excluem documentos com base na expressão do filtro . A expressão pode incluir campos diferentes de chaves de índice e pode especificar condições diferentes de um campo existente.
Por exemplo, um índice parcial pode implementar o mesmo comportamento de um Enterprise Advanced. Este índice parcial suporta as mesmas queries que um Enterprise Advanced no campo name :
db.users.createIndex( { name: 1 }, { partialFilterExpression: { name: { $exists: true } } } )
No entanto, um índice parcial também pode filtrar em campos diferentes da chave de índice. Por exemplo, um índice parcial no campo name pode verificar a existência do campo email :
db.users.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.users.find( { name: "Ned Stark", email: { $regex: /gameofthron\.es$/ } } )
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.users.find( { name: "Ned Stark", email: { $exists: false } } )
Índices TTL parciais
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.
Restrições
Você não pode especificar a opção
partialFilterExpressione a opçãosparse._idos í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
partialFilterExpressionnão poderá fazer referência a um campo criptografado.
Índices equivalentes
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.
Por exemplo, você não pode criar dois índices que diferem apenas nas maiúsculas e minúsculas do texto na expressão de filtro parcial.
Exemplos
Os exemplos nesta página usam dados do conjunto de dados de amostra sample_mflix. Para obter detalhes sobre como carregar esse conjunto de dados em sua implantação autogerenciada do MongoDB , consulte Carregar o conjunto de dados de amostra. Se você fez modificações nos bancos de dados de amostra, talvez seja necessário descartar e recriar os bancos de dados para executar os exemplos nesta página.
Criar um índice parcial em uma collection
O exemplo seguinte adiciona um índice parcial nos campos title e genres. A operação indexa apenas documentos onde o campo rating é PG:
db.movies.createIndex( { title: 1, genres: 1 }, { partialFilterExpression: { rated: "PG" } } )
A seguinte query na collection movies usa o índice parcial para retornar os roteiristas de todos os filmes intitulados "Os Três Mosquetes":
db.movies.find( { title: "The Three Musketeers", genres: ["Action", "Adventure", "Comedy"], rated: "PG" }, { writers: 1 } )
No entanto, a seguinte query não pode utilizar o índice parcial porque o predicado da query não inclui o filtro rating:
db.movies.find( { genres: "Drama" }, { title: 1 } ).limit(5)
Índice parcial com restrição única
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.
A seguinte operação na users collection cria um índice que especifica uma restrição exclusiva no email campo e uma expressão de filtro password: { $exists: true } parcial.
db.users.createIndex( { name: 1 }, { name: "name_partial_unique_idx", unique: true, partialFilterExpression: { password: { $exists: true } } } )
O índice impede a inserção dos documentos para um endereço de e-mail que já existe na coleção e um campo password existente.
No entanto, os seguintes documentos com endereços de e-mail duplicados são permitidos, pois a restrição exclusiva se aplica apenas a documentos com um 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" } ] )