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 .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
Atlaschevron-right

Explorando recursos de pesquisa com o Atlas Search

Aasawari Sahasrabuddhe9 min read • Published Jul 30, 2024 • Updated Aug 20, 2024
SpringAtlasJava
APLICATIVO COMPLETO
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Bem-vindo à segunda parte de nossa série sobre como aproveitar o MongoDB Atlas Search com o Spring Boot. Na Parte 1, aprenderam como criar índices do Atlas Search usando vários métodos: o MongoDB CLI, a UI do Atlas e programaticamente dentro de um aplicativo Spring Boot. Exploramos as etapas fundamentais necessárias para configurar esses índices, fornecendo uma base sólida para implementar recursos avançados de pesquisa.
Nesta parte, vamos construir sobre essa base, mergulhando mais fundo na aplicação prática desses índices. Este artigo se concentrará na criação e execução de consultas de pesquisa usando o Spring Boot, ilustrando como aproveitar todo o potencial do Atlas Search em seus aplicativos.
Também explicaremos os principais conceitos e terminologias associados ao Atlas Search, garantindo que você tenha uma compreensão abrangente de como ele funciona.
Quer você seja um desenvolvedor habilidoso ou novo no MongoDB e no Spring Boot, esta série tem como objetivo fornecer-lhe o conhecimento e as ferramentas necessárias para implementar uma funcionalidade de pesquisa eficiente e eficaz em seus aplicativos.

Pré-requisitos

  1. Um Atlas cluster dedicado para criar índices programaticamente
  2. Versão Java 22
  3. Dados de amostra carregados no seu cluster do Atlas

Consultando com índices de pesquisa do Atlas

Antes de escrevermos queries de pesquisa usando os índices que criamos, recomendamos que você se familiarize com os conceitos fundamentais do MongoDB Atlas Search. Um ótimo recurso para fazer isso é a parte 1 da série "Getting Started with MongoDB Atlas Search and Java".
Este tutorial fornecerá a você uma compreensão dos princípios chaves por trás do Atlas Search e demonstrará como criar diferentes tipos de índices personalizados para vários casos de uso. Ao obter esse conhecimento básico, você estará mais bem equipado para implementar e aproveitar com eficácia as funcionalidades de pesquisa em seus aplicativos Spring Boot.
Em cada uma das seções abaixo, abordaremos a terminologia e entenderemos exemplos da vida real em que os índices seriam úteis.
As queries de pesquisa mencionadas serão usadas na coleção defilmes do banco de dados sample_mflix

Caso 1: definindo propriedades dinâmicas como verdadeiras

Se você tiver um aplicativo em que o esquema muda com frequência, a configuração da propriedade dinâmica como true criará automaticamente os índices nos campos de tipo de dados suportados . Por exemplo, o testIndex01 tem o mapeamento dinâmico para true, que indexa todos os campos com tipos de dados compatíveis .
A função abaixo usa testIndex01 para consultar todos os campos do índice de string.
1public ArrayList<Document> searchMovies(String query) {
2 List<Document> pipeline = Arrays.asList(new Document("$search",
3 new Document("index", "testIndex01")
4 .append("text",
5 new Document("query", "cartoon")
6 .append("path", Arrays.asList("title", "plot", "fullplot")))),
7 new Document("$project",
8 new Document("_id", 0L)
9 .append("title", 1L)
10 .append("plot", 1L)
11 .append("fullplot", 1L)),
12 new Document("$limit", 3L));
13
14ArrayList<Document> results = new ArrayList<>();
15collection.aggregate(pipeline).into(results);
16return results;
17 }
Usando a função acima, você pode encontrar filmes que mencionam a palavra- chave mencionada na _query _on nos campos title , plot e fullplot definidos no caminho. _por exemplo...
1curl -X GET "http://localhost:8080/search?query=cartoon" | jq
...dará todos os filmes com a palavra-chave "cartoon ", conforme mostrado abaixo:
1[
2 {
3 "plot": "Follow Garfield behind the scenes in Cartoon World where he grows bored with his life as a comic strip star.",
4 "title": "Garfield Gets Real",
5 "fullplot": "Follow Garfield behind the scenes in Cartoon World where he grows bored with his life as a comic strip star."
6 },
7 {
8 "plot": "A high-profiled documentary about Hergè and his major cartoon success, Tintin, based in part on previously unreleased archive tape footage.",
9 "title": "Tintin and I",
10 "fullplot": "A high-profiled documentary about Hergè and his major cartoon success, Tintin, based in part on previously unreleased archive tape footage."
11 },
12 {
13 "plot": "Bugs Bunny reflects on his past cartoon exploits.",
14 "title": "The Bugs Bunny/Road-Runner Movie",
15 "fullplot": "The Bugs Bunny/Road Runner Movie is basically a collection of Warner Bros. short cartoon features, \"starring\" the likes of Daffy Duck, Porky Pig and Wile.E.Coyote. These animations are interspersed by Bugs Bunny reminiscing on past events and providing links between the individual animations which are otherwise unconnected. The Road Runner feature at the end consists of sketches from various RR separates (well it does in the 78-minute version anyway)."
16 }
17]

Caso 2: Usando analyzers em índices de pesquisa

Nesse caso, utilizaremos o testIndex02 criado com o mapeamento de campo. Mapeamento de campo significa que o mapeamento estático foi usado e nem todos os campos são índices. Somente os campos mencionados são indexados.
Em nosso caso, o campo _genre _foi indexado e pode ser usado com o método abaixo:
1public ArrayList<Document> searchMoviesWithGenre(String keyword){
2 List<Document> pipeline = Arrays.asList(new Document("$search",
3 new Document("index", "testIndex02")
4 .append("text",
5 new Document("query", keyword)
6 .append("path", "genres"))),
7 new Document("$project",
8 new Document("_id", 0L)
9 .append("title", 1L)
10 .append("genres", 1L)),
11 new Document("$limit", 5L));
12ArrayList<Document> results = new ArrayList<>();
13collection.aggregate(pipeline).into(results);
14return results;
15 }
Por exemplo, se você quiser listar todos os filmes cujo gênero é ação, pode fazer a chamada REST como:
1curl -X GET "localhost:8080/searchMoviesWithGenre?query=action" | jq
Isso dará o resultado como:
1[
2 {
3 "genres": [
4 "Action"
5 ],
6 "title": "The Perils of Pauline"
7 },
8 {
9 "genres": [
10 "Action"
11 ],
12 "title": "Legacy of Rage"
13 },
14 {
15 "genres": [
16 "Action"
17 ],
18 "title": "Batman Returns"
19 },
20 {
21 "genres": [
22 "Action"
23 ],
24 "title": "Dragon Inn"
25 },
26 {
27 "genres": [
28 "Action"
29 ],
30 "title": "Dikiy vostok"
31 }
32]

Caso 3: Usando facets para categorizar os dados

A partir do exemplo acima, usaremos as facetas usadas pelo métodosearchMoviesAndCategorize para realizar uma pesquisa por gêneros e categorizar os dados com base nos gêneros. Mais tarde, o testIndex02 também tem numberFacet criado no campoano, que agrupará todos os filmes lançados a cada 10 anos e retornará a contagem de todos os filmes.
1public ArrayList<Document> searchMoviesAndCategorise(){
2 List<Document> pipeline = Arrays.asList(new Document("$searchMeta",
3 new Document("index", "testIndex02")
4 .append("facet",
5 new Document("operator",new Document("text",
6 new Document("query", "movie").append("path", "title")))
7 .append("facets",new Document("genresFacet",
8 new Document("type", "string").append("path", "genres"))
9 .append("yearFacet",new Document("type", "number")
10 .append("path", "year")
11 .append("boundaries", Arrays.asList(1990L, 2000L, 2010L, 2020L)))))));
12ArrayList<Document> results = new ArrayList<>();
13collection.aggregate(pipeline).into(results);
14return results;
15}
Por exemplo, quando você usa a chamada de API abaixo, ela categoriza primeiro os dados com base nos gêneros e depois categoriza o número de filmes lançados a cada 10 anos até o momento.
1curl -X GET "http://localhost:8080/searchMoviesAndCategorise" | jq
Isso dará o resultado como:
1 {
2 "count": {
3 "lowerBound": 125
4 },
5 "facet": {
6 "genresFacet": {
7 "buckets": [
8 {
9 "_id": "Comedy",
10 "count": 71
11 },
12 {
13 "_id": "Animation",
14 "count": 42
15 },
16 {
17 "_id": "Adventure",
18 "count": 40
19 },
20 {
21 "_id": "Family",
22 "count": 29
23 },
24 {
25 "_id": "Drama",
26 "count": 19
27 },
28 {
29 "_id": "Action",
30 "count": 18
31 },
32 {
33 "_id": "Documentary",
34 "count": 16
35 },
36 {
37 "_id": "Horror",
38 "count": 9
39 },
40 {
41 "_id": "Fantasy",
42 "count": 6
43 },
44 {
45 "_id": "Crime",
46 "count": 5
47 }
48 ]
49 },
50 "yearFacet": {
51 "buckets": [
52 {
53 "_id": 1990,
54 "count": 19
55 },
56 {
57 "_id": 2000,
58 "count": 62
59 },
60 {
61 "_id": 2010,
62 "count": 27
63 }
64 ]
65 }
66 }
67 }
68]

Caso 4: pesquisar texto com ortografia incompleta

O recursode preenchimento automático ajuda você a pesquisar usando palavras-chave que estão escritas de forma incompleta. Esse recurso é útil quando um usuário deseja procurar um livro com um nome incompleto no site de comércio eletrônico. Neste caso, usaremos o testIndex03 e procuraremos filmes em que foram mencionadas palavras-chave incompletas para os camposfullplot.
A função de pesquisa pode ser escrita como:
1public ArrayList<Document> searchWithIncompleteKeyword(String keyword){
2 List<Document> pipeline = Arrays.asList(new Document("$search",
3 new Document("index", "testIndex03")
4 .append("autocomplete",
5 new Document("query", keyword)
6 .append("path", "fullplot"))
7 .append("highlight",
8 new Document("path", "fullplot"))),
9 new Document("$project",
10 new Document("_id", 0L)
11 .append("fullplot", 1L)
12 .append("highlights",
13 new Document("$meta", "searchHighlights"))),
14 new Document("$limit", 1L));
15ArrayList<Document> results = new ArrayList<>();
16collection.aggregate(pipeline).into(results);
17return results;
18 }
Por exemplo, se o campofullplot mencionar Spa e Cow como palavras-chave incompletas para testar Espanha, Espaço, cowboys etc., você poderá pesquisar usando a seguinte API.
1curl -X GET "http://localhost:8080/searchMoviesWithAutocomplete?query=spa%20cow" | jq
Ele dará uma resposta como:
1[
2 {
3 "fullplot": "Julièn Torralba is a former movie stuntman in Almeria, Spain. He and several of his colleagues, who once made a living in American Westerns shot in Spain, now are reduced to doing stunt shows for minuscule audiences on the decaying set built for those old Westerns. Julièn wrestles with dark memories of the death of his son, also a stuntman, and with estrangement from his daughter-in-law Laura and her son Carlos. Carlos, a young boy, becomes intrigued with his late father's life and runs away to join Julièn and his band of has-beens. There Carlos is initiated into the rambunctious life of these hard-drinking faux cowboys. But when Laura, a powerful executive looking for a new site for a tourist resort, learns that Carlos has joined the hated Julièn, she moves to destroy even this remnant of Julièn's once-proud career. Julièn and the cowboys decide to fight back the only way they know how.",
4 "highlights": [
5 {
6 "score": 2.126451015472412,
7 "path": "fullplot",
8 "texts": [
9 {
10 "value": "Julièn Torralba is a former movie stuntman in Almeria, ",
11 "type": "text"
12 },
13 {
14 "value": "Spain. He and",
15 "type": "hit"
16 }
17 ]
18 },
19 {
20 "score": 1.518623948097229,
21 "path": "fullplot",
22 "texts": [
23 {
24 "value": "He and several of his colleagues, who once made a living in American Westerns shot in ",
25 "type": "text"
26 },
27 {
28 "value": "Spain, now are",
29 "type": "hit"
30 },
31 {
32 "value": " reduced to doing stunt shows for minuscule audiences on the decaying set built for those old Westerns. ",
33 "type": "text"
34 }
35 ]
36 },
37 {
38 "score": 1.869809865951538,
39 "path": "fullplot",
40 "texts": [
41 {
42 "value": "There Carlos is initiated into the rambunctious life of these hard-drinking faux ",
43 "type": "text"
44 },
45 {
46 "value": "cowboys. But when",
47 "type": "hit"
48 }
49 ]
50 },
51 {
52 "score": 1.9461908340454102,
53 "path": "fullplot",
54 "texts": [
55 {
56 "value": "Julièn and the ",
57 "type": "text"
58 },
59 {
60 "value": "cowboys decide to",
61 "type": "hit"
62 },
63 {
64 "value": " fight back the only way they know how.",
65 "type": "text"
66 }
67 ]
68 }
69 ]
70 }
71]

Caso 5: pesquisa com ortografia incorreta

Às vezes, pesquisamos itens/produtos em sites usando a grafia errada devido à correção automática ou ao desconhecimento da grafia correta, mas o aplicativo ainda nos fornece os resultados corretos. Isso é possível devido ao recurso de pesquisa difusa.
O Atlas Search do MongoDB também permite que você pesquise o texto com a ortografia incorreta.
O testIndex03 criado na parte anterior da série será usado aqui na função abaixo:
1public ArrayList<Document> searchWithMisspelledTitle(String keyword){
2 List<Document> result = Arrays.asList(new Document("$search",
3 new Document("index", "testIndex03")
4 .append("text",
5 new Document("query", keyword)
6 .append("path", "title")
7 .append("fuzzy",
8 new Document("maxEdits", 2L)
9 .append("maxExpansions", 100L)))),
10 new Document("$project",
11 new Document("title", 1L)
12 .append("cast", 1L)),
13 new Document("$limit", 3L));
14return collection.aggregate(result).into(new ArrayList<>());
15 }
Nesse caso, você pode pesquisar o filme com um título escrito incorretamente, e o nome correto do filme aparecerá nos resultados.
Por exemplo, se você pesquisar o filme com a chamada REST abaixo...
1curl -X GET "localhost:8080/searchMoviesWithIncorrectSpelling?query=Gerti%20the%20Dinosor" | jq
... quando a palavra Dinosour for escrita erroneamente como Dinosor, ela fornecerá os resultados como :
1[
2 {
3 "_id": {
4 "timestamp": 1463423888,
5 "date": "2016-05-16T18:38:08.000+00:00"
6 },
7 "cast": [
8 "Winsor McCay",
9 "George McManus",
10 "Roy L. McCardell"
11 ],
12 "title": "Gertie the Dinosaur"
13 },
14 {
15 "_id": {
16 "timestamp": 1463423899,
17 "date": "2016-05-16T18:38:19.000+00:00"
18 },
19 "title": "Dinosaur",
20 "cast": [
21 "D.B. Sweeney",
22 "Alfre Woodard",
23 "Ossie Davis",
24 "Max Casella"
25 ]
26 },
27 {
28 "_id": {
29 "timestamp": 1463423974,
30 "date": "2016-05-16T18:39:34.000+00:00"
31 },
32 "cast": [
33 "Stan Adelstein",
34 "Lanice Archer",
35 "Robert Bakker",
36 "Philip Currie"
37 ],
38 "title": "Dinosaur 13"
39 }
40]

Caso 6: Pesquisar com palavras-chave sinônimos

Semelhante ao caso mencionado acima, o MongoDB Atlas Search também permite a pesquisa com palavras-chave sinônimas, ou seja, palavras que têm o mesmo significado ou quase o mesmo significado.
Para explorar este recurso, utilizamos o testIndex04 para escrever a query de pesquisa.
Quando criamos o índice de pesquisa, especificamos a coleção como Coleção de origem dos sinônimos, de onde os sinônimos serão mapeados. O testIndex04 menciona o nome da collection como test_synonyms, que é a collection de origem.
A query de pesquisa é escrita como:
1public ArrayList<Document> searchWithSynonyms(String keyword){
2 List<Document> result = Arrays.asList(new Document("$search",
3 new Document("index", "testIndex04")
4 .append("text",
5 new Document("path", "fullplot")
6 .append("query", keyword)
7 .append("synonyms", "synonymName"))),
8 new Document("$limit", 10L),
9 new Document("$project",
10 new Document("_id", 0L)
11 .append("title", 1L)
12 .append("fullplot", 1L)
13 .append("score",
14 new Document("$meta", "searchScore"))),
15 new Document("$limit", 3L));
16 return collection.aggregate(result).into(new ArrayList<>());
17 }
O $meta usado na query com searchScore determinará a proximidade do documento da palavra-chave pesquisada. Antes de fazermos o restante da chamada para testar a query, precisamos criar o mapeamento para os sinônimos em uma collection diferente.
Insira os dados abaixo na coleção test_synonyms.
1[
2 {
3 mappingType: 'explicit',
4 input: [ 'love', 'romance' ],
5 synonyms: [ 'love', 'romance' ]
6 },
7 {
8 mappingType: 'equivalent',
9 synonyms: [ 'car', 'vehicle', 'automobile' ]
10 }
11]
Para testar a query acima, você pode usar a chamada REST como:
1curl -X GET "localhost:8080/searchMoviesWithSynonyms?query=love" | jq
Isso fornecerá resultados com base no mapeamento criado, conforme mostrado abaixo.
1[
2 {
3 "title": "Oh, Woe Is Me",
4 "fullplot": "Romance about Simon Donnadieu and his decision to leave his ever-loving wife Rachel.",
5 "score": 3.9741177558898926
6 },
7 {
8 "title": "27 Missing Kisses",
9 "fullplot": "The summerly adventures of teen Sybilla, who falls in love with a middle-aged father, while being romanced by the his teen son.",
10 "score": 3.8209657669067383
11 },
12 {
13 "title": "The End of the Affair",
14 "fullplot": "In wartorn London Maurice Bendrix falls in love with neighbor Sarah Miles. They begin an illicit romance behind Sarah's husband's back. While war does not last forever, neither does love in this existentialist tale.",
15 "score": 3.753319263458252
16 }
17]
O código completo para o aplicativo usando todos os casos mencionados acima está disponível no repositório do GitHub.

Limpar os índices

Depois de utilizar todos os índices criados, você pode usar o método abaixo para excluir todos os índices de pesquisa que foram criados por meio do aplicativo.
1public void deleteSearchIndexes(String dbName, String collectionName) {
2 MongoDatabase database = mongoClient.getDatabase(dbName);
3 MongoCollection<Document> collection = database.getCollection(collectionName);
4
5 List<String> indexNames = new ArrayList<>();
6 for (Document indexInfo : collection.listSearchIndexes()) {
7 String indexName = indexInfo.getString("name");
8 if (!"_id_".equals(indexName)) {
9 indexNames.add(indexName);
10 }
11 }
12 // Drop each index using its name from the array
13 for (String indexName : indexNames) {
14 collection.dropSearchIndex(indexName);
15 }
16 System.out.println("Deleted all indexes created");
17 }
E chame a API com o comando abaixo
1curl -X DELETE "localhost:8080/deleteSearchIndexes?dbName=<dbName>&collectionName=<collectionName>"

Conclusão

Nesta segunda parte de nossa série sobre como explorar o MongoDB Atlas Search com o Spring Boot, analisamos as aplicações práticas dos índices de pesquisa que criamos na Parte 1. Ao demonstrar vários cenários de pesquisa, destacamos a versatilidade e o poder do Atlas Search em lidar com diferentes tipos de consultas e estruturas de dados.
Nesta parte, abordamos alguns casos de uso como autocompletar, fuzzy, mapeamento de campo etc. Se quiser saber mais sobre outros casos, também temos outros artigos - MongoDB Atlas Search Using the Java Driver and Spring Data e How to Build a Search Service in Java - nos quais você pode explorar mais casos de uso.
Se você tiver dúvidas ou sugestões, fique à vontade para entrar em contato no MongoDB Community e também para explorar mais tutoriais interessantes por meio do nosso MongoDB Developer Center.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
{Parte de uma série
Atlas Search com inicialização de primavera
Próximo
Continuar

Mais nesta série
Relacionado
Podcast

Episódio 1 da série de podcasts de aniversário de 5 anos do Atlas – Do Onramp ao Atlas


Aug 17, 2023 | 22 min
Tutorial

IoT e MongoDB: impulsionando a análise de séries temporais do consumo doméstico de energia


Aug 28, 2024 | 6 min read
Artigo

Como criar aplicativos sem servidor com SST e MongoDB Atlas


Aug 29, 2024 | 3 min read
Tutorial

Consulta flexível com Atlas Search


Jul 12, 2024 | 3 min read
Sumário