‫Instrutor: Nesta aula,
‫vamos aprender sobre consultas geoespaciais para implementar um
‫recurso muito legal, que é fornecer
‫uma funcionalidade de pesquisa para passeios dentro de uma
‫certa distância de um ponto especificado.
‫Digamos que você
‫more em um determinado ponto e queira saber quais
‫passeios começam a uma certa distância de você, como 250
‫milhas, porque você não quer dirigir mais
‫longe para iniciar sua experiência de passeio.
‫Seria um recurso incrível e
‫um caso de uso muito bom de consultas geoespaciais.
‫E para implementar algo assim, aqui em
‫nosso roteador turístico, poderíamos criar uma rota
‫legal, algo assim.
‫Vou colocá-lo aqui antes das rotas gerais
‫aqui.
‫Digamos que a rota de ponto do roteador
‫seja chamada de tours internos, certo?
‫Em seguida, também precisamos especificar a distância.
‫Portanto, criamos um parâmetro de distância aqui.
‫Em seguida, também precisamos especificar o
‫centro, que é basicamente o ponto onde você mora.
‫Então, vamos especificá-lo ao redor do centro e depois
‫barra, latitude e longitude.
‫Então, basicamente nesta variável aqui,
‫você quer passar as coordenadas do lugar onde
‫você está.
‫Digamos que você more em Los
‫Angeles e queira encontrar todos os passeios a uma
‫distância de 300 milhas.
‫Então aqui você diria
‫300, e aqui você colocaria as
‫coordenadas de basicamente onde você mora, certo?
‫Então, vamos fornecer também a opção de especificar
‫a unidade.
‫Então, se essa distância aqui for em quilômetros ou milhas.
‫Digamos, unidade de
‫barra e a unidade como parâmetro.
‫Agora, essa maneira de especificar um URL é algo
‫que nunca fizemos antes.
‫Então, basicamente, dizendo aqui centro e barra e
‫colocando a longitude e latitude depois
‫disso, e a unidade
‫de barra e, depois disso, o parâmetro de consultas.
‫E, claro, também
‫podemos fazer com que o usuário
‫especifique todas essas opções usando uma string de consulta,
‫mas dessa forma parece muito mais limpo e também é uma forma padrão de
‫especificar URLs que contêm muitos objetos.
‫Então, o que eu estava dizendo é que, em vez disso,
‫poderíamos fazer isso, é claro.
‫Percorre a distância e então o usuário teria que fornecer
‫a distância assim aqui.
‫E o centro assim, digamos menos 40
‫e 45, e então a unidade também define para milhas.
‫Ok, então esta tem sido uma maneira de usar strings
‫de consulta e já fizemos isso antes.
‫E na verdade não assim, mas assim.
‫Ok, mas em vez disso,
‫vamos especificá-lo novamente assim.
‫O que, na minha opinião, parece muito melhor.
‫Então, menos 40, 45.
‫Ok, então acho que isso aqui
‫realmente parece muito mais limpo do que isso.
‫Ok, e isso é outra coisa que
‫eu queria mostrar a vocês
‫que é uma espécie de padrão de especificação de URL assim, certo?
‫De qualquer forma,
‫para esta rota, é claro, precisamos de um
‫manipulador de rota, que estará no
‫controlador de tour, e vamos chamar essa função de manipulador para obter os tours.
‫E então agora vamos implementar este
‫método neste manipulador.
‫Então, controlador de turnê e bem aqui.
‫E vamos começar obtendo todos os parâmetros.
‫Então, deixe-me copiar tudo isso aqui.
‫E só para sabermos como são os nossos dados.
‫Tudo bem?
‫Então isso, e então isso tem um comentário.
‫Tudo bem, então vamos usar uma reestruturação simples para obter todos
‫os nossos dados de uma vez a partir dos parâmetros.
‫E, na verdade,
‫precisamos dizer const, distância e unidade.
‫Então, tudo isso vem de parâmetros de ponto de solicitação.
‫Ok, então por diante req. params, temos a distância do
‫ponto, o centro do ponto e a unidade do ponto, certo?
‫Porque esses são os nomes
‫dos três parâmetros que especificamos aqui.
‫E na verdade
‫não é o centro, é latlng aqui, ok,
‫então esse é o correto e, finalmente, a unidade.
‫Então, novamente, usamos a reestruturação para obter todas essas
‫variáveis de uma vez.
‫A seguir, vamos realmente obter todas
‫as coordenadas desta variável de latitude e longitude aqui.
‫Como podemos ver, esperamos os dados no formato como este,
‫e isso torna realmente fácil copiar esses dados
‫do Google Maps.
‫Então, deixe-me mostrar isso rapidamente para você.
‫É importante que você entenda como esse tipo
‫de coisa também funciona na prática.
‫Portanto, vamos usar o exemplo de Los Angeles aqui.
‫Ok, digamos que você more em algum lugar aqui.
‫Ok, então você pode facilmente obter a latitude e
‫a longitude assim, ok?
‫Então, coloque isso aqui, apenas como um exemplo novamente.
‫E então este é o formato.
‫Parece latitude e longitude.
‫E agora vamos criar uma variável para cada um deles.
‫Portanto, um para latitude e outro para longitude.
‫Então, o ponto de latitude e longitude se divide porque é
‫uma string e queremos separá-lo por vírgula.
‫E isso criará um array de
‫dois elementos, e agora podemos usar novamente a destruição para
‫salvá-los nas duas variáveis nas quais estamos interessados.
‫Então, latitude e longitude.
‫Ok, em seguida, quero testar se realmente temos as
‫variáveis de longitude e latitude para encontrar.
‫Porque senão, isso significa que o usuário não
‫os especificou no formato exigido.
‫Então, digamos que se
‫não houver latitude ou longitude, queremos criar um novo erro.
‫Como sempre, erro de novo aplicativo, e não tenho certeza se ainda
‫o temos, bem aqui, e na verdade
‫não temos.
‫Portanto, comentamos esta parte porque não precisamos mais do erro do
‫aplicativo depois de criar nossas funções de fábrica do
‫manipulador, mas agora, na verdade, precisamos dele novamente e, portanto, vamos
‫trazê-lo de volta.
‫E a mensagem aqui
‫vai ser, por favor, forneça, no formato, assim.
‫E o código de erro 400 para essa solicitação.
‫Ótimo, e agora apenas para ver se tudo isso
‫está funcionando
‫corretamente, vamos apenas fazer o logout disso no console.
‫A distância dessa longitude e unidade.
‫E vamos também enviar uma mensagem genérica aqui,
‫apenas para realmente finalizar o ciclo de solicitação de resposta.
‫E por isso é claro é o mesmo de sempre.
‫Portanto, status de sucesso por agora, e é claro que
‫mais tarde enviaremos os dados que a consulta retorna.
‫Então, na verdade, vamos copiar isso aqui.
‫Porque isso já é o que a gente quer.
‫Então, de volta ao Postman, vamos encerrar tudo isso.
‫Este nós não precisamos mais.
‫Tudo bem, também não precisamos estar logados e
‫também não queremos nenhuma atualização.
‫De qualquer forma, também precisamos pegar esta parte que
‫estou com preguiça de escrever.
‫E então vamos testar isso agora.
‫E isso não funcionou,
‫e acho que esse aqui chamamos de tours, na verdade.
‫Nós?
‫Então, passeios dentro.
‫Então, não sei por que escrevi
‫distância aqui, vamos corrigir isso rapidamente aqui em nossos exemplos.
‫E é claro que são passeios internos.
‫E isso ainda não está funcionando, então vamos dar uma olhada
‫e rotear a implementação aqui.
‫Então aqui temos isso, e sim,
‫claro, isso não é correto de forma alguma.
‫Portanto, este aqui não deve estar dentro da rota de pontos, obviamente.
‫Mas, em vez disso, deve estar no método get.
‫E agora isso se parece muito mais com o
‫que temos aqui.
‫Então, rota de ponto e, em seguida, ponto obtenha.
‫Então, uma tentativa a menos e desta vez funcionou.
‫E vamos dar uma olhada
‫no console e, de fato, aqui temos
‫a distância que é especificada a latitude e longitude, e a unidade.
‫Ótimo, agora é hora de
‫realmente escrever a consulta.
‫Agora, uma consulta geoespacial realmente funciona
‫de forma bastante semelhante a uma consulta regular.
‫Então, ainda vamos escrever turnês é igual a turnê. encontrar, e
‫claro, aguardando o resultado desta promessa.
‫E então o velho jogo de marcar tudo
‫como assíncrono e então pegar o assíncrono e embrulhar nossa função
‫lá.
‫Portanto, temos todos os passeios
‫não usados aqui, então vamos prosseguir e editar o
‫objeto de resposta imediatamente.
‫Portanto, dados, e agora lembre-se de como os chamamos de dados.
‫E então passeios.
‫Ok, e tudo o que precisamos fazer é
‫especificar ou filtrar o objeto aqui.
‫Portanto, lembre-se de que queremos
‫basicamente consultar o local de início,
‫porque o campo do local de início
‫é o que mantém o ponto geoespacial onde cada passeio começa.
‫E é exatamente isso que estamos procurando.
‫Portanto, comece a localização e agora precisamos especificar
‫o valor que estamos procurando.
‫E, para isso, agora usaremos um operador
‫geoespacial chamado geo within.
‫Como sempre, precisamos especificar
‫o assunto e, então, aqui, onde
‫usaríamos anteriormente como algum operador matemático como
‫maior que, desta vez usamos um operador geoespacial como este.
‫Geo dentro, e esse operador faz exatamente o que diz.
‫Basicamente, ele encontra documentos dentro de uma determinada geometria.
‫E essa geometria é o que precisamos definir como a próxima etapa.
‫Queremos encontrar
‫documentos, mas onde realmente queremos encontrar esses documentos?
‫Bem, queremos encontrá-los dentro de uma esfera
‫que começa neste ponto que definimos,
‫e que tem um raio da distância que definimos.
‫Então, novamente com nosso exemplo em Los
‫Angeles, se você especificar
‫a distância de 250 milhas, isso significa que você deseja
‫encontrar todos os documentos turísticos dentro de uma esfera com um raio de 250 milhas.
‫Ok, faz sentido?
‫E agora precisamos passar
‫as informações aqui para o operador geo dentro, certo?
‫E fazemos isso definindo uma esfera central.
‫Ok, e novamente, eu sei que isso parece
‫um tanto confuso, mas é por isso que estou explicando aqui passo a passo.
‫E também em um segundo,
‫vamos dar uma olhada na documentação.
‫Portanto, o operador da esfera
‫central obtém uma matriz das coordenadas e do raio.
‫E vamos formatar o código aqui
‫para, pelo menos, torná-lo um pouco mais fácil, certo?
‫Bem, parece o mesmo, mas de qualquer maneira, é
‫assim que você encontra as coordenadas aqui.
‫E, para isso, precisamos de outro
‫array e, em seguida, a longitude e a latitude.
‫E isso mesmo.
‫Primeiro, você precisa sempre definir
‫a longitude e depois a latitude, o que é
‫um pouco contra-intuitivo porque geralmente os pares de coordenadas são
‫sempre especificados com a latitude primeiro e a longitude primeiro.
‫Acho que já mencionei isso
‫em geo adjacente, por algum motivo funciona assim.
‫Então esse é o centro da esfera.
‫Agora precisamos especificar seu raio.
‫Agora, aqui, na verdade, não passamos à distância, mas em
‫vez disso, espera-se um raio em uma unidade
‫especial chamada radianos.
‫Deixe-me colocar a variável radius
‫aqui e, em um segundo, vamos defini-la.
‫Então, vamos agora definir o raio.
‫Então, novamente, o raio é basicamente a
‫distância que queremos ter como
‫raio, mas convertida em uma unidade especial chamada radianos.
‫E para obter os
‫radianos, precisamos dividir nossa distância pelo
‫raio da Terra.
‫Parece um pouco louco, mas realmente é assim que funciona.
‫Ok, agora precisamos levar em consideração
‫nossas unidades aqui, porque é claro que o raio
‫da Terra é diferente em milhas e em quilômetros.
‫Então, vamos agora fazer um turnery
‫de maior aqui e dizer que se a unidade for igual a milhas,
‫então o resultado aqui deve ser a distância.
‫Então, basicamente nosso raio original dividido por 3963. 2
‫Ok, então novamente, esse é o raio da Terra em milhas.
‫Ok, caso contrário, vamos assumir que
‫é um quilômetro.
‫E se for quilômetros, então é a distância
‫dividida por 6.378. 1 quilômetro.
‫Tudo bem, então novamente, este tipo de conversão maluca aqui é necessária
‫porque normalmente seria esperado
‫que o raio de nossa esfera fosse em radianos.
‫E os radianos obtemos dividindo
‫a distância pelo raio da Terra.
‫Ótimo, então estamos quase prontos para testar isso agora.
‫Vamos apenas adicionar a propriedade results que costumávamos ter.
‫Basicamente, com o número de resultados,
‫e outra coisa
‫muito importante é que, na verdade,
‫para sermos capazes de fazer apenas consultas básicas, precisamos
‫primeiro atribuir um índice ao campo
‫onde os dados geoespaciais que procuramos estão armazenado.
‫Portanto, neste caso, precisamos adicionar um índice para o local de início.
‫Então, vamos fazer isso aqui no modelo de passeio.
‫Então, aqui embaixo, precisamos de outro índice.
‫Esquema de tour. índice.
‫Local de início, mas agora não vamos defini-lo como um ou
‫menos um, porque desta vez é
‫um índice diferente de
‫que precisamos.
‫Portanto, para dados geoespaciais, este índice precisa ser
‫um índice de esfera 2D se os dados descreverem pontos reais
‫na esfera como a Terra.
‫Ou, em vez disso, também podemos usar um índice
‫2D se estivermos usando apenas pontos fictícios em um plano bidimensional simples.
‫Agora, neste caso, é claro, estamos
‫falando sobre pontos reais na
‫superfície da Terra, então vamos usar um índice de esfera 2D aqui.
‫Então, uma esfera 2D como esta.
‫Ok, então estamos basicamente dizendo que este
‫local de início aqui deve ser indexado em uma esfera 2D.
‫Portanto, uma esfera semelhante à da Terra onde todos os nossos dados estão localizados.
‫Ótimo, e com isso, agora
‫devemos estar prontos para testar nossa nova rota.
‫Ok, vamos apenas aumentar este raio aqui
‫um pouco mais de 400 milhas, e então vamos ver o que temos.
‫Bem, recebemos este erro de aparência
‫estranha e não tenho certeza do que é.
‫E então, vamos dar uma olhada.
‫E provavelmente há algo errado aqui com o raio,
‫mas na verdade este é um ótimo momento para testar nosso depurador.
‫Então, eu mostrei isso a você há muito
‫tempo, mas este é um bom caso de uso para
‫realmente dar uma olhada no depurador novamente.
‫Então, acho que temos um script NPM para isso,
‫é chamado de depuração.
‫Portanto, precisamos conhecer esse processo e, em seguida, dizer NPM run debug.
‫OK?
‫Isso deve abrir esta bela janela.
‫E vamos fechar todos esses arquivos aqui.
‫Ok, então estamos em nossos controladores.
‫Controlador de tour.
‫E agora, vamos definir um ponto de interrupção bem aqui.
‫Ok, porque neste ponto, teremos todas as
‫nossas variáveis definidas, e então
‫podemos dar uma olhada em seus valores para ver o que está acontecendo.
‫Claro que poderíamos fazer isso com
‫um console simples. log, mas em
‫algumas situações em que há muitas
‫coisas acontecendo e também é bom usar o depurador.
‫Portanto, precisamos enviar nosso pedido.
‫E agora estamos no depurador em nosso ponto de interrupção.
‫E então, neste
‫momento, nosso código realmente parou.
‫E podemos ver aqui que,
‫na verdade, todas as nossas variáveis parecem estar definidas.
‫Vamos dar uma olhada nisso aqui no local.
‫Então temos a distância,
‫temos a latitude, a longitude e também o raio.
‫Então, vamos continuar aqui.
‫Então pulamos para a
‫direita para a próxima linha porque este if aqui não entrava no bloco if.
‫E agora está executando todas essas funções.
‫Mas vamos sair deles
‫na verdade, e agora teremos tours indefinidos.
‫Portanto, se continuarmos com
‫isso, provavelmente obteremos o mesmo erro novamente, certo?
‫E, de fato, nós fazemos.
‫Portanto, deve ser algo aqui
‫nesta linha, digamos, e de fato, acho que encontrei o erro.
‫Então é assim que você escreve esfera.
‫Então a esfera é mais assim, certo?
‫Portanto, espero e acredito que realmente tenha sido esse o erro.
‫Então, vamos realmente fechar o depurador aqui,
‫e vamos aliviar, e realmente isso deve atualizar
‫meu código aqui.
‫Vamos ver, e realmente não aconteceu.
‫Não tenho certeza do porquê, mas tudo bem.
‫Vamos executar isso aqui novamente.
‫Não este comando, ok de
‫qualquer maneira, vamos apenas iniciar o NPM.
‫Feche tudo isso.
‫E agora tente novamente.
‫Ah, e agora temos alguns resultados reais aqui, ótimo.
‫Isso me diz que esses passeios aqui estão
‫naquela distância de 400 milhas especificada.
‫Mas como podemos saber realmente que é verdade?
‫Bem, na verdade podemos usar uma bússola para isso.
‫Então, se abrirmos a bússola aqui, temos algo muito
‫bom que é esse esquema.
‫Então vamos fazer isso aqui nos tours.
‫E agora podemos chegar ao esquema aqui e, em
‫seguida, analisar esse esquema.
‫Portanto, analise o esquema e, agora, temos um
‫bom resumo de todos os nossos campos.
‫Por exemplo,
‫você vê que a dificuldade é
‫fácil em 50% dos documentos, média em 30% e difícil em 20%.
‫Você também vê essas durações.
‫Portanto, em 20% são cinco e nove também é mais popular do
‫que as outras durações.
‫Agora, o que realmente estou interessado aqui são os locais.
‫Ou, na verdade, os locais de início, então isso está aqui.
‫E agora, normalmente, você veria um mapa aqui.
‫Mas agora, não há nenhum mapa porque temos
‫um documento agora que não tem uma localização inicial.
‫Portanto, para que
‫isso funcione corretamente, precisamos nos livrar desse documento.
‫Então, foi um desses documentos
‫de teste que criamos, mas agora não precisamos mais.
‫Deixe-me ver se aparece aqui.
‫Talvez seja no final.
‫Então, sim, é esta nova turnê de teste.
‫Vamos nos livrar disso.
‫De volta ao nosso esquema, vamos analisá-lo novamente.
‫Ok, então aqui temos os aplicativos estrela.
‫E aqui você já vê o mapa, isso é ótimo, certo?
‫Esse é um recurso realmente útil.
‫Portanto, devemos ter nove pontos aqui.
‫Então, um, dois, três, quatro, cinco, seis, sete, oito, um
‫aqui em cima, o nono.
‫Portanto, provavelmente este é para ver a Aurora Boreal.
‫Direito?
‫E agora aqui podemos realmente replicar essa consulta
‫usando esta interface gráfica.
‫Então vamos para Los Angeles e aproximadamente
‫ao ponto onde estávamos.
‫Digamos aqui, estou diminuindo um pouco o
‫zoom para dar mais
‫espaço, mas agora podemos apertar Shift e arrastar.
‫Assim como diz aqui embaixo.
‫Então coloque a mão onde estava nosso ponto, basicamente
‫em algum lugar aqui em Los Angeles.
‫Agora mude e arraste, agora tudo bem.
‫E então você pode ver que conforme
‫começamos a aumentar esta esfera, vamos cada vez
‫mais em direção a mais alguns desses pontos aqui ficando amarelos, certo?
‫E eu acreditava que nosso raio era algo como 0. 1,
‫ou algo assim, digamos.
‫E então você vê que na verdade são
‫três documentos, então três passeios dentro desta esfera
‫que acabamos de criar, certo?
‫Portanto, temos esta esfera com raio 0. 1, como você pode
‫ver aqui.
‫E então, de fato, essa consulta se parece
‫com aquela que acabamos de preencher com o código em nossa função
‫de controlador, certo?
‫Obtemos esses três documentos que estão marcados como
‫laranja, então vamos agora clicar em analisar novamente e
‫agora nossa consulta retornou três documentos.
‫Então, vamos ver os nomes na verdade.
‫Onde fica isso?
‫Para o amante de esportes, o degustador de
‫vinhos e o campista do parque.
‫E os três tours que obtivemos
‫no Postman, como resultado da API, devem ser exatamente esses três.
‫Portanto, o amante de esportes, degustador de vinhos e campista do parque.
‫Então, campista do parque, o amante dos esportes, e o
‫último a se
‫lembrar deveria ser o provador de vinhos,
‫e de fato é.
‫Ótimo, isso é realmente fantástico.
‫Agora vamos diminuir para 200, vamos ver
‫quantos resultados você consegue, e na
‫verdade é apenas um.
‫Então, vamos voltar à bússola aqui.
‫Vamos deletar essa consulta aqui.
‫Portanto, se voltarmos a todos os nossos documentos,
‫dê uma olhada em nosso mapa.
‫E então aqui está LA, certo.
‫É outro raio que deve ser algo como 0. 05
‫Agora, algo assim, digamos, de
‫fato, só temos um tour que acredito
‫ser o degustador de vinhos ou algo assim.
‫Sim, temos que analisar isso.
‫Então, ah, na verdade é o amante dos esportes.
‫E então vamos ver se é isso que temos aqui.
‫E realmente é.
‫Então, é o amante dos esportes,
‫e esse é o único passeio que fica a 200 milhas de Los Angeles.
‫Fantástico.
‫Então isso eu acho muito, muito excitante, muito legal.
‫Deixe-me mostrar outra coisa rapidamente,
‫para que você também possa ver todas as nossas localizações no mapa.
‫Então está aqui.
‫E esses são os locais de
‫todos os passeios, aqueles que estão armazenados no local.
‫Portanto, temos as coordenadas e também os dias,
‫as descrições e a hora, certo?
‫E é claro que nossa consulta não é sobre tudo isso aqui.
‫Para essa consulta, realmente nos preocupamos
‫apenas com a localização das estrelas, mas eu ainda
‫queria mostrar a vocês este mapa onde podemos ver todas as localizações também.
‫Ok, então há realmente um grande potencial para usar
‫dados geoespaciais com o MongoDB.
‫As possibilidades são infinitas para fazer
‫consultas geoespaciais como esta.
‫Na verdade, gostaria de
‫mostrar se temos mais alguns operadores geoespaciais no MongoDB.
‫Então, vamos dar uma olhada na documentação aqui novamente.
‫Então, vamos descer aqui novamente
‫para a referência e os operadores, e os operadores de consulta.
‫E eu acho que está em algum lugar aqui, sim.
‫Então, aqui temos o operador geoespacial.
‫E você vê que este é o que usamos,
‫portanto, aquele que seleciona geometrias
‫dentro de uma geometria adjacente geográfica delimitadora.
‫Isso soa um pouco estranho, mas essa geometria
‫adjacente geográfica delimitadora é aquela esfera que definimos
‫em nosso código, certo?
‫Agora também poderíamos ter usado o snear aqui,
‫vamos dar uma olhada nisso.
‫E então isso pareceria um pouco diferente.
‫Nesse caso, teríamos de definir o ponto usando
‫a longitude e a latitude que obtivemos,
‫e então especificaríamos a distância
‫máxima aqui em metros.
‫E então, neste caso,
‫não precisamos fazer a conversão para radianos.
‫Ok, o que também é bom
‫sobre este é que podemos especificar uma distância mínima.
‫E assim, poderíamos, por exemplo, excluir passeios
‫que estão a apenas 50 milhas de distância do nosso ponto
‫de partida, certo?
‫Portanto, se algum dia você
‫precisar de algo assim, também poderá usar o novo operador aqui.
‫Certo, ótimo.
‫Portanto, com essa consulta geoespacial que
‫acabamos de definir aqui, basicamente encontramos documentos localizados a
‫uma certa distância do nosso ponto de partida.
‫Mas e se realmente quiséssemos saber as
‫distâncias exatas de todos os passeios até aquele ponto de partida?
‫Bem, isso é exatamente o que vamos calcular
‫na próxima aula.