Você pode pensar no índice de campo único do MongoDB como uma matriz, com ponteiros para locais de documentos. Por exemplo, se você tiver uma coleção com (observe que a sequência está deliberadamente fora de ordem):
[collection]
1: {a:3, b:2}
2: {a:1, b:2}
3: {a:2, b:1}
4: {a:1, b:1}
5: {a:2, b:2}
Índice de campo único
Agora se você fizer:
db.collection.createIndex({a:1})
O índice se parece aproximadamente com:
[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1
Observe três coisas importantes:
- É classificado por
a
ascendente - Cada entrada aponta para o local onde residem os documentos relevantes
- O índice registra apenas os valores do
a
campo. Ob
campo não existe no índice de forma alguma
Então, se você fizer uma consulta como:
db.collection.find().sort({a:1})
Tudo o que ele precisa fazer é percorrer o índice de cima para baixo, buscando e exibindo o documento apontado pelas entradas. Observe que você também pode percorrer o índice de baixo para cima, por exemplo:
db.collection.find().sort({a:-1})
e a única diferença é que você anda o índice ao contrário.
Porque
b
não está no índice, você não pode usar o índice ao consultar qualquer coisa sobre b
. Índice composto
Em um índice composto, por exemplo:
db.collection.createIndex({a:1, b:1})
Isso significa que você deseja classificar por
a
primeiro, depois classifique por b
. O índice ficaria assim:[index a:1, b:1]
1: {a:1, b:1} --> 4
2: {a:1, b:2} --> 2
3: {a:2, b:1} --> 3
4: {a:2, b:2} --> 5
5: {a:3, b:2} --> 1
Observe que:
- O índice é classificado de
a
- Em cada
a
você tem umb
ordenado - Você tem 5 entradas de índice contra apenas três no exemplo anterior de campo único
Usando este índice, você pode fazer uma consulta como:
db.collection.find({a:2}).sort({b:1})
Ele pode encontrar facilmente onde
a:2
em seguida, caminhe o índice para a frente. Dado esse índice, você não pode fazer :db.collection.find().sort({b:1})
db.collection.find({b:1})
Em ambas as consultas, você não pode encontrar facilmente
b
uma vez que está espalhado por todo o índice (ou seja, não em entradas contíguas). No entanto, você pode Faz:db.collection.find({a:2}).sort({b:-1})
já que você pode encontrar essencialmente onde o
a:2
são, e percorra o b
entradas para trás. Editar :esclarecimento da pergunta do @marcospgp no comentário:
A possibilidade de usar o índice
{a:1, b:1}
para satisfazer find({a:2}).sort({b:-1})
realmente faz sentido se você vê-lo do ponto de vista de uma tabela classificada. Por exemplo, o índice {a:1, b:1}
pode ser pensado como:a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
localizar({a:2}).sort({b:1})
O índice
{a:1, b:1}
significa sort by a, then within each a, sort the b values
. Se você fizer um find({a:2}).sort({b:1})
, o índice sabe onde estão todos os a=2
são. Dentro deste bloco de a=2
, o b
seria classificada em ordem crescente (de acordo com a especificação do índice), de modo que a consulta find({a:2}).sort({b:1})
pode ser satisfeita por:a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block forward to satisfy
2 | 2 <-- find({a:2}).sort({b:1})
2 | 3 <--
3 | 1
3 | 2
localizar({a:2}).sort({b:-1})
Como o índice pode ser andado para frente ou para trás, um procedimento semelhante foi seguido, com uma pequena torção no final:
a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block backward to satisfy
2 | 2 <-- find({a:2}).sort({b:-1})
2 | 3 <--
3 | 1
3 | 2
O fato de o índice poder avançar ou retroceder é o ponto chave que habilita a consulta
find({a:2}).sort({b:-1})
para poder usar o índice {a:1, b:1}
. Explicação do planejador de consultas
Você pode ver o que o planejador de consultas planeja usando
db.collection.explain().find(....)
. Basicamente, se você vir um stage
de COLLSCAN
, nenhum índice foi usado ou pode ser usado para a consulta. Consulte explicar resultados
para obter detalhes sobre a saída do comando.