Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
Atlaschevron-right

Consulta flexível com Atlas Search

Ethan Steininger3 min read • Published Oct 04, 2022 • Updated Jul 12, 2024
GraphQLAtlasPesquisaJavaScript
SNIPPET
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty

Introdução

Neste tutorial, mostrarei como a flexibilidade dos índices invertidos do Atlas Search é uma opção poderosa em comparação aos índices de árvore B tradicionais quando se trata de suporte a consultas ad hoc.

O que é consulta flexível?

Os mecanismos de query flexíveis oferecem a capacidade de executar uma query de alto desempenho que abrange vários índices em seu armazenamento de dados. Isso significa que você pode escrever queries ad-hoc e geradas dinamicamente, onde você não precisa conhecer a query, os campos ou a ordem dos campos com antecedência.
Certifique-se de verificar a documentação do MongoDBsobre este assunto!
É muito raro o planejador de query do MongoDB selecionar um plano que envolva vários índices. Neste tutorial, percorreremos um cenário em que isso se torna um requisito.

Sua aplicação está em constante evolução

Digamos que você tenha um aplicativo de filmes com documentos como:
1{
2 "title": "Fight Club",
3 "year": 1999,
4 "imdb": {
5 "rating": 8.9,
6 "votes": 1191784,
7 "id": 137523
8 },
9 "cast": [
10 "Edward Norton",
11 "Brad Pitt"
12 ]
13}

Requisitos iniciais do produto

Agora, para a versão 1.0 aplicativo, você precisa consultar o título e o ano, portanto, primeiro crie um índice composto por meio de:
db.movies.createIndex( { "title": 1, "year": 1 } )
Então emita a query:
db.movies.find({"title":"Fight Club", "year":1999})
Ao executar um plano de explicação, você tem uma consulta perfeita com uma 1:1 proporção de documentos examinados para documentos retornados:
1{
2 "executionStats": {
3 "executionSuccess": true,
4 "nReturned": 1,
5 "executionTimeMillis": 0,
6 "totalKeysExamined": 1,
7 "totalDocsExamined": 1
8 }
9}

Nossa consulta então precisa evoluir

Agora, nossos requisitos de aplicativo evoluíram e você precisa consultar no cast e no imdb. Primeiro você cria o índice:
db.movies.createIndex( { "cast": 1, "imdb.rating": 1 } )
Então emita a query:
db.movies.find({"cast":"Edward Norton", "imdb.rating":{ $gte:9 } })
Não é a maior proporção de documentos examinados para documentos retornados, mas ainda não é ruim:
1{
2 "executionStats": {
3 "executionSuccess": true,
4 "nReturned": 7,
5 "executionTimeMillis": 0,
6 "totalKeysExamined": 17,
7 "totalDocsExamined": 17
8 }
9}

Agora nossa query envolve novamente

Agora, nosso aplicativo exige que você emita uma nova consulta, que se torna um subconjunto do original:
db.movies.find({"imdb.rating" : { $gte:9 } })
A consulta acima resulta na temida varredura de coleção, apesar de o índice composto anterior (cast_imdb.rating) incluir a chave da consulta acima. Isso ocorre porque o campo "imdb.rating" não é o prefixo do índice, e a consulta não contém condições de filtro no campo "cast"."
Observação: as varreduras de coleção devem ser evitadas porque elas não apenas instruem o cursor a examinar todos os documentos da coleção que são lentos, mas também forçam os documentos a sair da memória, resultando em aumento da pressão de E/S.
Os resultados do nosso plano de query são os seguintes:
1{
2 "executionStats": {
3 "executionSuccess": true,
4 "nReturned": 31,
5 "executionTimeMillis": 26,
6 "totalKeysExamined": 0,
7 "totalDocsExamined": 23532
8 }
9}
Agora você realmente poderia criar um novo índice composto apenas por imdb.rating, que retornaria uma verificação de índice para a query acima, mas são três índices diferentes nos quais o planejador de queries teria que navegar para selecionar a resposta de melhor desempenho.
Como o Lucene usa uma estrutura de dados de índice diferente (índices invertidos versus índicesde árvore B), ele foi criado especificamente para executar queries que se sobrepõem em vários índices.
Ao contrário dos índices compostos, a ordem dos campos na definição do índice do Atlas Search não é importante. Os campos podem ser definidos em qualquer ordem. Portanto, ele não está sujeito à limitação acima, em que uma consulta que esteja apenas em um campo sem prefixo de um índice composto não pode usar o índice.
Se você criar um único índice que mapeie todos os nossos quatro campos acima (titulo, ano, elenco, imdb):
1{
2 "mappings": {
3 "dynamic": false,
4 "fields": {
5 "title": {
6 "type": "string",
7 "dynamic": false
8 },
9 "year": {
10 "type": "number",
11 "dynamic": false
12 },
13 "cast": {
14 "type": "string",
15 "dynamic": false
16 },
17 "imdb.rating": {
18 "type": "number",
19 "dynamic": false
20 }
21 }
22 }
23}
Em seguida, você emite uma query que primeiro abrange o título e o ano por meio de uma cláusula obrigatória (E), que é equivalente a db.collection.find({"title":"Fight Club", "year":1999}):
1[{
2 "$search": {
3 "compound": {
4 "must": [{
5 "text": {
6 "query": "Fight Club",
7 "path": "title"
8 }
9 },
10 {
11 "range": {
12 "path": "year",
13 "gte": 1999,
14 "lte": 1999
15 }
16 }
17 ]
18 }
19 }
20}]
Os resultados correspondentes do planejador de query:
1{
2 '$_internalSearchIdLookup': {},
3 'executionTimeMillisEstimate': 6,
4 'nReturned': 0
5}
Então, quando você adicionar imdb e cast à query, ainda poderá obter resultados de desempenho:
1[{
2 "$search": {
3 "compound": {
4 "must": [{
5 "text": {
6 "query": "Fight",
7 "path": "title"
8 },
9 {
10 "range": {
11 "path": "year",
12 "gte": 1999,
13 "lte": 1999
14 },
15 {
16 "text": {
17 "query": "Edward Norton",
18 "path": "cast"
19 }
20 },
21 {
22 "range": {
23 "path": "year",
24 "gte": 1999,
25 "lte": 1999
26 }
27 }
28 ]
29 }
30 }
31 }]
Os resultados correspondentes do planejador de query:
1{
2 '$_internalSearchIdLookup': {},
3 'executionTimeMillisEstimate': 6,
4 'nReturned': 0
5}

Este não é um cenário singular

Os aplicativos evoluem conforme as expectativas e os requisitos de nossos usuários. Para dar suporte à evolução dos requisitos de seus aplicativos, os índices padrão de árvore B simplesmente não podem evoluir na mesma taxa que um índice invertido.

Casos de uso

Aqui estão vários exemplos em que as estruturas de dados de índice invertido do Atlas Search podem ser úteis, com links para material de referência:
  • GraphQL: se o ponto de entrada do seu banco de dados é GraphQL, onde as queries são definidas pelo cliente, então você é um candidato ideal para índices invertidos
  • Pesquisa avançada: você precisa expandir os critérios de filtragem da sua barra de pesquisa além de vários campos.
  • Pesquisa de curinga: pesquisa em campos que correspondem a combinações de caracteres e curingas.
  • Query ad-hoc: a necessidade de gerar dinamicamente queries sob demanda por nossos clientes.

Recursos


Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Artigo

Mapa do Coronavírus e rastreador de dados ao vivo com o MongoDB Charts


Nov 15, 2023 | 3 min read
Tutorial

Como implantar o MongoDB Atlas com AWS CloudFormation


Mar 20, 2024 | 6 min read
Tutorial

Simplificar o gerenciamento de registros para o Amazon S3 usando exportações de registros baseadas em Atlas Push com o HashiCorp Terraform


Jul 08, 2024 | 6 min read
Artigo

Atlas Online Archive: gerencie com eficiência o ciclo de vida dos dados


Apr 23, 2024 | 8 min read
Sumário
  • Recursos