Consultar no Amazon DocumentDB
Esta seção explica todos os aspectos da consulta com o Amazon DocumentDB.
Tópicos
Consultar documentos
Às vezes, pode ser necessário examinar o inventário da sua loja online para que os clientes possam visualizar e comprar o que você está vendendo. Consultar uma coleção é relativamente fácil, quer você queira todos os documentos na coleção ou apenas os documentos que satisfazem a um critério específico.
Para consultar documentos, use a operação find()
. O comando find()
tem um único parâmetro do documento que define os critérios a serem usados na escolha dos documentos a serem retornados. A saída de find()
é um documento formatado como uma única linha de texto sem quebras de linha. Para formatar o documento de saída para facilitar a leitura, use find().pretty()
. Todos os exemplos deste tópico usam .pretty()
para formatar a saída.
Os exemplos de código a seguir usam os quatro documentos que você inseriu na coleção example
nos dois exercícios anteriores — insertOne()
e insertMany()
que estão localizados na seção Adicionar documentos de Trabalhando com documentos.
Tópicos
Recuperar todos os documentos em uma coleção
Para recuperar todos os documentos em sua coleção, use a operação find()
com um documento de consulta vazio.
A consulta a seguir retorna todos os documentos da coleção example
.
db.example.find( {} ).pretty()
Recuperar documentos que correspondem a um valor de campo
Para recuperar todos os documentos que correspondem a um campo e valor, use a operação find()
com um documento de consulta que identifica os campos e valores a serem correspondidos.
Usando documentos anteriores, essa consulta retorna todos os documentos em que o campo "Item" será igual a "Pen".
db.example.find( { "Item": "Pen" } ).pretty()
Recuperar documentos que correspondem a um documento incorporado
Para localizar todos os documentos que correspondem a um documento incorporado, use a operação find()
com um documento de consulta que especifica o nome do documento incorporado e todos os campos e valores desse documento incorporado.
Ao vincular um documento incorporado, o documento incorporado do documento deve ter o mesmo nome que na consulta. Além disso, os campos e os valores no documento incorporado devem corresponder à consulta.
A consulta a seguir retorna apenas o documento "Poster Paint". Isso ocorre porque a "Caneta" tem valores diferentes para "OnHand
" e "MinOnHand
", e a "Tinta spray" tem um campo a mais (OrderQnty
) que o documento de consulta.
db.example.find({"Inventory": { "OnHand": 47, "MinOnHand": 50 } } ).pretty()
Recuperar documentos que correspondem a um valor de campo em um documento incorporado
Para localizar todos os documentos que correspondem a um documento incorporado, use a operação find()
com um documento de consulta que especifica o nome do documento incorporado e todos os campos e valores desse documento incorporado.
Considerando os documentos anteriores, a consulta a seguir usa "notação de pontos" para especificar o documento incorporado e os campos de interesse. Qualquer documento que seja correspondente será retornado, independentemente de quais outros campos possam estar presentes no documento incorporado. A consulta retorna "Poster Paint" e "Spray Paint", pois ambos correspondem aos campos e valores especificados.
db.example.find({"Inventory.OnHand": 47, "Inventory.MinOnHand": 50 }).pretty()
Recuperar documentos que correspondem a uma matriz
Para localizar todos os documentos que correspondem a uma matriz, use a operação find()
com o nome da matriz de interesse e todos os valores na matriz. A consulta retorna todos os documentos que têm uma matriz com esse nome, com valores idênticos aos da matriz, e na mesma ordem que na consulta.
A consulta a seguir retorna apenas o documento "Pen", pois o "Poster Paint" tem uma cor adicional (White), e "Spray Paint" tem as cores em ordem diferente.
db.example.find( { "Colors": ["Red","Green","Blue","Black"] } ).pretty()
Recuperar documentos que correspondem a um valor em uma matriz
Para localizar todos os documentos que possuem um valor de matriz específico, use a operação find()
com o valor e o nome da matriz de interesse.
db.example.find( { "Colors": "Red" } ).pretty()
A operação anterior retorna todos os três documentos, pois cada um deles tem uma matriz chamada Colors
e o valor Red
em algum lugar da matriz. Se você especificar o valor "White
", a consulta retornará apenas "Tinta de cartaz".
Recuperar documentos usando operadores
A consulta a seguir retorna todos os documentos em que o valor "Inventory.OnHand
" é inferior a 50.
db.example.find( { "Inventory.OnHand": { $lt: 50 } } )
Para obter uma lista de operadores de consulta compatíveis, consulte Operadores de consulta e projeção.
Plano de consulta
Como posso ver os executionStats
de um plano de consulta?
Ao determinar por que uma consulta está sendo executada mais lentamente do que o esperado, pode ser útil entender quais são os executionStats
desse plano de consulta. O executionStats
fornece o número de documentos retornados de um estágio específico (nReturned
), a quantidade de tempo de execução gasto em cada estágio (executionTimeMillisEstimate
) e o tempo necessário para gerar um plano de consulta (planningTimeMillis
). É possível determinar os estágios mais demorados de sua consulta para ajudar a concentrar seus esforços de otimização na saída de executionStats
, como mostrado nos exemplos de consulta abaixo. No momento, o parâmetro executionStats
não é compatível com os comandos delete
e update
.
nota
O Amazon DocumentDB emula a API do MongoDB 3.6 em um mecanismo de banco de dados criado para fins específicos que utiliza um sistema de armazenamento distribuído, tolerante a falhas e autorrecuperável. Como resultado, os planos de consulta e a saída de explain()
podem diferir entre o Amazon DocumentDB e o MongoDB. Os clientes que desejam ter controle sobre seu plano de consulta podem usar o operador $hint
para impor a seleção de um índice preferencial.
Execute a consulta que você deseja melhorar com o comando explain()
da seguinte forma.
db.runCommand({explain: {query document}}). explain("executionStats").executionStats;
Veja a seguir um exemplo de operação.
db.fish.find({}).limit(2).explain("executionStats");
A saída dessa operação é semelhante à seguinte.
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.fish",
"winningPlan" : {
"stage" : "SUBSCAN",
"inputStage" : {
"stage" : "LIMIT_SKIP",
"inputStage" : {
"stage" : "COLLSCAN"
}
}
}
},
"executionStats" : {
"executionSuccess" : true,
"executionTimeMillis" : "0.063",
"planningTimeMillis" : "0.040",
"executionStages" : {
"stage" : "SUBSCAN",
"nReturned" : "2",
"executionTimeMillisEstimate" : "0.012",
"inputStage" : {
"stage" : "LIMIT_SKIP",
"nReturned" : "2",
"executionTimeMillisEstimate" : "0.005",
"inputStage" : {
"stage" : "COLLSCAN",
"nReturned" : "2",
"executionTimeMillisEstimate" : "0.005"
}
}
}
},
"serverInfo" : {
"host" : "enginedemo",
"port" : 27017,
"version" : "3.6.0"
},
"ok" : 1
}
Se estiver interessado em ver apenas o executionStats
da consulta acima, você pode usar o seguinte comando. Para coleções pequenas, o processador de consultas do Amazon DocumentDB pode optar por não usar um índice se os ganhos de desempenho forem insignificantes.
db.fish.find({}).limit(2).explain("executionStats").executionStats;
Cache do plano de consultas
Para otimizar o desempenho e reduzir a duração do planejamento, o Amazon DocumentDB armazena internamente os planos de consulta em cache. Isso permite que consultas com a mesma forma sejam executadas diretamente usando um plano em cache.
No entanto, esse armazenamento em cache às vezes pode causar um atraso aleatório para a mesma consulta; por exemplo, uma consulta que normalmente leva um segundo para ser executada pode, ocasionalmente, levar dez segundos. Isso ocorre porque, com o tempo, a instância do leitor armazenou em cache várias formas da consulta, consumindo memória. Se você tiver essa lentidão aleatória, não é necessário fazer nada para liberar a memória. O sistema gerenciará o uso da memória para você e, quando a memória atingir um determinado limite, ela será liberada automaticamente.
Explicar os resultados
Se você quiser retornar informações sobre planos de consulta, o Amazon DocumentDB oferece suporte ao modo de verbosidade queryPlanner
. Os resultados do explain
retornam o plano de consulta selecionado escolhido pelo otimizador em um formato semelhante ao seguinte:
{ "queryPlanner" : { "plannerVersion" : <int>, "namespace" : <string>, "winningPlan" : { "stage" : <STAGE1>, ... "inputStage" : { "stage" : <STAGE2>, ... "inputStage" : { ... } } } } }
As seções a seguir definirão os resultados explain
comuns.
Tópicos
Estágio de digitalização e filtragem
O otimizador pode escolher um dos seguintes escaneamentos:
COLLSCAN
Esse estágio é um escaneamento de coleta sequencial.
{ "stage" : "COLLSCAN" }
IXSCAN
Esse estágio verifica as teclas de índice. O otimizador pode recuperar o documento nesse estágio e isso pode resultar em um estágio FETCH anexado posteriormente.
db.foo.find({"a": 1}) { "stage" : "IXSCAN", "direction" : "forward", "indexName" : <idx_name> }
FETCH
Se o otimizador recuperou documentos em um estágio diferente do IXSCAN, o resultado incluirá um estágio FETCH. Por exemplo, a consulta IXSCAN acima pode resultar em uma combinação dos estágios FETCH e IXSCAN:
db.foo.find({"a": 1}) { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "indexName" : <idx_name> } }
O IXONLYSCAN verifica somente a chave de índice. Criar índices compostos não evitará o FETCH.
Interseção de índices
IXAND
O Amazon DocumentDB pode incluir um estágio IXAND com uma matriz InputStages do IXSCAN se puder utilizar a interseção de índices. Por exemplo, podemos ver resultados como:
{ "stage" : "FETCH", "inputStage" : { "stage" : "IXAND", "inputStages" : [ { "stage" : "IXSCAN", "indexName" : "a_1" }, { "stage" : "IXSCAN", "indexName" : "b_1" } ] } }
União de índices
IXOR
Semelhante à interseção de índices, o Amazon DocumentDB pode incluir o estágio IXOR
com uma matriz inputStages
para o operador $or
.
db.foo.find({"$or": [{"a": {"$gt": 2}}, {"b": {"$lt": 2}}]})
Para a consulta acima, a saída de explicação pode ter a seguinte aparência:
{ "stage" : "FETCH", "inputStage" : { "stage" : "IXOR", "inputStages" : [ { "stage" : "IXSCAN", "indexName" : "a_1" }, { "stage" : "IXSCAN", "indexName" : "b_1" } ] } }
Interseção/união de vários índices
O Amazon DocumentDB pode combinar vários estágios de interseção ou união de índices e, em seguida, buscar o resultado. Por exemplo:
{ "stage" : "FETCH", "inputStage" : { "stage" : "IXOR", "inputStages" : [ { "stage" : "IXSCAN", ... }, { "stage" : "IXAND", "inputStages" : [ { "stage" : "IXSCAN", ... }, { "stage" : "IXSCAN", ... } ] } ] } }
O uso de estágios de interseção ou união de índices não é afetado pelo tipo de índice (esparso, composto, etc.).
Índice composto
O uso do índice composto do Amazon DocumentDB não está limitado aos subconjuntos iniciais dos campos indexados; ele pode usar o índice com a parte do sufixo, mas pode não ser muito eficiente.
Por exemplo, o índice composto de { a: 1, b: -1 }
pode oferecer suporte às três consultas abaixo:
db.orders.find( { a: 1 } } )
db.orders.find( { b: 1 } } )
db.orders.find( { a: 1, b: 1 } } )
Fase de classificação
Se houver um índice na(s) chave(s) de classificação solicitada(s), o Amazon DocumentDB poderá usar o índice para obter a ordem. Nesse caso, o resultado não incluirá um estágio SORT
, mas sim um estágio IXSCAN
. Se o otimizador preferir uma classificação simples, ele incluirá um estágio como este:
{ "stage" : "SORT", "sortPattern" : { "a" : 1, "b" : -1 } }
Fase de grupos
O Amazon DocumentDB oferece suporte a duas estratégias de grupo diferentes:
SORT_AGGREGATE
: agregação de classificação no disco.HASH_AGGREGATE
: agregação de hash na memória.