Sparse Indexes
Nesta página
Índices esparsos contêm somente entradas para documentos que têm o campo indexado, mesmo que o campo de índice contenha um valor nulo. O índice ignora qualquer documento que não tenha o campo indexado. O índice é "esparso" porque não inclui todos os documentos de uma collection. Por outro lado, índices não escassos contêm todos os documentos em uma collection, armazenando valores nulos para os documentos que não contêm o campo indexado.
Importante
O MongoDB oferece a opção de criar índices parciais. Os índices parciais oferecem um superconjunto da funcionalidade de índices escassos. Deve-se preferir índices parciais em relação a índices esparsos.
Crie um índice esparso
Para criar um índice esparso, utilize o método db.collection.createIndex()
com a opção sparse
definida como true
.
Por exemplo, a seguinte operação em mongosh
cria um índice esparso no campo xmpp_id
da coleção addresses
:
db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )
O índice não indexa documentos que não incluem o campo xmpp_id
.
Observação
Não confunda índices escassos do MongoDB com índices de nível de bloco em outros bancos de dados. Pense neles como índices densos com um filtro específico.
Comportamento
Índice de análise e resultados incompletos
Se um índice esparso resultaria em um conjunto de resultados incompleto para queries e operações de classificação, o MongoDB não utilizará este índice a menos que um hint()
especifique explicitamente o índice.
Por exemplo, a query { x: { $exists: false } }
não usará um índice esparso no campo x
, a menos que seja explicitamente sugerido. Para ver um exemplo que detalha o comportamento, consulte Um índice esparso em uma coleção não retorna resultados completos.
Se você incluir um hint()
que especifica um índice esparso ao executar uma count()
de todos os documentos em uma coleção (ou seja, com um predicado de query vazio), o índice esparso será utilizado mesmo que resulte em uma contagem incorreta.
db.collection.insertOne( { _id: 1, y: 1 } ); db.collection.createIndex( { x: 1 }, { sparse: true } ); db.collection.find().hint( { x: 1 } ).count();
Para obter a contagem correta, não hint()
com um índice esparso ao executar uma contagem de todos os documentos em uma coleção.
db.collection.find().count(); db.collection.createIndex( { y: 1 } ); db.collection.find().hint( { y: 1 } ).count();
Índices que são esparsos por padrão
Os seguintes tipos de índice são sempre escassos:
Índices de compostos esparsos
Os índices compostos podem conter diferentes tipos de índices esparsos. A combinação de tipos de índice determina como o índice composto corresponde aos documentos.
Esta tabela resume o comportamento de um índice composto que contém diferentes tipos de índices esparsos:
Componentes do índice composto | Comportamento do índice composto |
---|---|
Ascending indexes Descending indexes | Somente indexa documentos que contêm um valor para pelo menos uma das chaves. |
Indexa um documento somente quando ele contém um valor para um dos campos | |
Somente indexa um documento quando ele corresponde a um dos campos |
sparse
e unique
propriedades
Um índice que seja esparso e exclusivo evita que uma collection tenha documentos com valores duplicados para um campo, mas permite vários documentos que omitem a chave.
Exemplos
Criar um índice esparso em uma collection
Considere uma collection scores
que contenha os seguintes documentos:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 } { "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
A collection tem um índice esparso no campo score
:
db.scores.createIndex( { score: 1 } , { sparse: true } )
Em seguida, a seguinte query na collection scores
usa o índice esparso para retornar os documentos que têm o campo score
menor que($lt
) 90
:
db.scores.find( { score: { $lt: 90 } } )
Como o documento para o userid"newbie"
não contém o campo score
e, portanto, não atende aos critérios da query, esta pode usar o índice esparso para retornar os resultados:
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
Um índice esparso em uma collection não retorna resultados completos
Considere uma collection scores
que contenha os seguintes documentos:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 } { "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
A collection tem um índice esparso no campo score
:
db.scores.createIndex( { score: 1 } , { sparse: true } )
Como o documento para o userid "newbie"
não contém o campo score
, o índice esparso não contém uma entrada para esse documento.
Considere a seguinte query para retornar todos os documentos da collection scores
, classificados pelo campo score
:
db.scores.find().sort( { score: -1 } )
Mesmo que a classificação seja pelo campo indexado, o MongoDB não selecionará o índice esparso para atender à query a fim de retornar resultados completos:
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 } { "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
Para utilizar o índice esparso, especifique explicitamente o índice com hint()
:
db.scores.find().sort( { score: -1 } ).hint( { score: 1 } )
O uso do índice resulta na devolução somente dos documentos com o campo score
:
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
Índice esparso com restrição única
Considere uma collection scores
que contenha os seguintes documentos:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 } { "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
Você pode criar um índice com uma restrição única e filtro esparso no campo score
utilizando a seguinte operação:
db.scores.createIndex( { score: 1 } , { sparse: true, unique: true } )
Esse índice permitiria a inserção de documentos que tivessem valores exclusivos para o campo score
ou que não incluíssem um campo score
. Dessa forma, considerando-se os documentos existentes na collection scores
, o índice permite as seguintes operações de inserção:
db.scores.insertMany( [ { "userid": "newbie", "score": 43 }, { "userid": "abby", "score": 34 }, { "userid": "nina" } ] )
No entanto, o índice não permitiria a adição dos seguintes documentos, pois já existem documentos com valor score
de 82
e 90
:
db.scores.insertMany( [ { "userid": "newbie", "score": 82 }, { "userid": "abby", "score": 90 } ] )
Índices únicos esparsos e não esparsos
A partir do MongoDB 5.0, índices esparsos exclusivos e não esparsos exclusivos com o mesmo padrão de chave podem existir em uma única coleção.
Criação de índice único e esparso
Este exemplo cria vários índices com o mesmo padrão de chave e diferentes opções sparse
:
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } ) db.scoreHistory.createIndex( { score : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )
Criação de índice básico e esparso
Você também pode criar índices básicos com o mesmo padrão de chave com e sem a opção esparsa:
db.scoreHistory.createIndex( { score : 1 }, { name: "sparse_index", sparse: true } ) db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )