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 .

Learn why MongoDB was selected as a leader in the 2024 Gartner® Magic Quadrant™
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
Atlaschevron-right

Adicione abreviações postais dos EUA à sua pesquisa do Atlas em 5 minutos

Ksenia Samokhvalova, Amelia Short9 min read • Published Sep 29, 2022 • Updated Sep 29, 2022
Atlas
Ícone do FacebookÍcone do Twitterícone do linkedin
Desenho de código com lupa
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Há casos em que ajuda ter sinônimos configurados para trabalhar com o índice do Atlas Search. Por exemplo, se a pesquisa em seu aplicativo precisar funcionar com endereços, talvez seja útil configurar uma lista de sinônimos comuns para abreviações postais, para que você possa digitar “blvd” em vez de “boulevard” e ainda encontrar todos os lugares com “boulevard” no endereço.
Este tutorial mostrará como configurar seu índice do Atlas Search para reconhecer abreviaturas postais dos EUA.

Pré-requisitos

Para ser bem-sucedido com este tutorial, você precisará de:
  • Python, para usar um script que raspa uma lista de abreviações de sufixo de rua compilada pelo Serviço Postal dos Estados Unidos (USPS). Este tutorial foi escrito usando Python 3.10.15, mas você pode testá-lo em versões anteriores do 3, se quiser.
  • Um cluster MongoDB Atlas. Siga o guiaIniciar com Atlas para criar sua conta e um cluster MongoDB. Para este tutorial, você pode usar seu cluster MongoDB Atlas gratuito para sempre! Anote o nome de usuário, a senha e a connection stringdo banco de dados,  pois você precisará deles mais tarde.
  • Rosetta, se você estiver em um MacOS com chip M1 . Isso permitirá que você execute ferramentas MongoDB como mongoimport e mongosh. 
  • mongosh para executar comandos na shell MongoDB. Se ainda não o tiver, instale o mongosh.
  • Uma cópia do mongoimport. Se você tiver o MongoDB instalado em sua estação de trabalho, talvez já tenha o mongoimport instalado. Caso contrário, siga as instruções no site do MongoDB para instalar o mongoimport
  • Vamos usar um conjunto de dados sample_restaurants neste tutorial, pois ele contém dados de endereço. Para obter instruções sobre como carregar dados de exemplo, consulte a documentação. Além disso, você pode ver todos os conjuntos de dados de exemplo disponíveis.
Os exemplos mostrados aqui foram todos escritos em um MacOS, mas devem ser executados em qualquer sistema do tipo unix. Se você estiver executando no Windows, recomendamos executar os comandos de exemplo dentro do subsistema do Windows para Linux.
Para saber mais sobre sinônimos no Atlas Search, sugerimos que você comece consultando nossa documentação. Os sinônimos permitem indexar e pesquisar em sua collection palavras que tenham o mesmo ou quase o mesmo significado ou, no caso de nosso tutorial, você pode pesquisar usando maneiras diferentes de escrever um endereço e ainda obter os resultados esperados. Para configurar e utilizar sinônimos no Atlas Search, você precisará:
  1. Crie uma collection no mesmo banco de dados da collection que você está indexando contendo os sinônimos. Observe que todos os documentos da coleção de sinônimos devem ter 
    um formato específico
    .
  2. Faça referência à sua coleção de sinônimos na definição do índice de pesquisa por meio de um mapeamento de sinônimos.
  3. Consulte seu mapeamento de sinônimos no comando $search com o operador $text
Orientaremos você por essas etapas no tutorial, mas primeiro, vamos começar criando os documentos JSON que formarão nossa collection de sinônimos.

Raspe a página de abreviações postais do USPS

Usaremos a lista de abreviações oficiais de sufixo de rua e uma lista de designadores de unidade secundária do site USPS para criar um JSON document para cada conjunto de sinônimos.
Todos os documentos da coleção de sinônimos devem ter um formato específico queespecifique o tipo de sinônimos: equivalente ou explícito. Os sinônimos explícitos têm um mapeamento unidirecional. Por exemplo, se "boat" for explicitamente mapeado para "sail,", estaremos dizendo que, se alguém pesquisar "boat,", queremos retornar todos os documentos que incluam "sail" e "boat.". No entanto, se pesquisarmos a palavra "sail,", não obteremos nenhum documento que tenha a palavra "boat." No caso de abreviações postais, no entanto, é possível usar todas as abreviações de forma intercambiável, portanto, usaremos o tipo de sinônimo "equivalent" no campo mappingType.
Aqui está um documento de amostra na collection de sinônimos para todas as possíveis abreviações de "avenue ":
1“Avenue”: 
2
3{
4
5"mappingType":"equivalent",
6
7"synonyms":["AVENUE","AV","AVEN","AVENU","AVN","AVNUE","AVE"]
8
9}
Escrevemos o código de web scraping para você em Python e você pode executá-lo com os seguintes comandos para criar um documento para cada grupo de sinônimos:
1git clone https://github.com/mongodb-developer/Postal-Abbreviations-Synonyms-Atlas-Search-Tutorial/ 
2
3cd Postal-Abbreviations-Synonyms-Atlas-Search-Tutorial
4
5python3 main.py
Para ver detalhes do código Python, leia o resto da seção.
Para raspar o site postal USPS , precisaremos importar os seguintes pacotes/bibliosteca e instalá-los usando PIP: requestslinda Soup epandas . Também queremos importar json e re para formatar nossos dados quando estivermos prontos:
1import json
2
3import requests
4
5from bs4 import BeautifulSoup
6
7import pandas as pd
8
9import re
Vamos começar com a página Abreviações de sufixo de rua. Queremos criar objetos que representem a URL e a própria página:
1# Create a URL object
2
3streetsUrl = 'https://pe.usps.com/text/pub28/28apc_002.htm'
4
5# Create object page
6
7headers = {
8
9    "User-Agent": 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Mobile Safari/537.36'}
10
11streetsPage = requests.get(streetsUrl, headers=headers)
Em seguida, queremos obter as informações da página. Começaremos analisando o HTML e, em seguida, obteremos a tabela por seu ID:
1# Obtain page's information
2
3streetsSoup = BeautifulSoup(streetsPage.text, 'html.parser')
1# Get the table by its id
2
3streetsTable = streetsSoup.find('table', {'id': 'ep533076'})
Agora que temos a tabela, vamos querer transformá-la em um dataframee formatá-la de uma forma que seja útil para nós:
1# Transform the table into a list of dataframes
2
3streetsDf = pd.read_html(str(streetsTable))
Uma coisa a se observar é que, na tabela fornecida no site do USPS, um nome principal geralmente é mapeado para vários nomes comumente usados. Tabela com nomes e abreviações do USPS Isso significa que precisamos agrupar dinamicamente os nomes comumente usados pelo nome primário correspondente e compilar isso em uma lista:
1# Group together all "Commonly Used Street Suffix or Abbreviation" entries
2
3streetsGroup = streetsDf[0].groupby(0)[1].apply(list)
Quando todos os nossos nomes estiverem agrupados, podemos percorrê-los e exportá-los como arquivos JSON individuais.
1for x in range(streetsGroup.size):
2
3
4    dictionary = {
5
6        "mappingType": "equivalent",
7
8        "synonyms": streetsGroup[x]
9
10    }
11
12
13    # export the JSON into a file
14
15    with open(streetsGroup.index.values[x] + ".json", "w") as outfile:
16
17        json.dump(dictionary, outfile)
Agora, vamos fazer a mesma coisa com a página Designadores de unidade secundária:
Assim como antes, começaremos obtendo a página e transformando-a em um dataframe:
1# Create a URL object
2
3unitsUrl = 'https://pe.usps.com/text/pub28/28apc_003.htm'
4
5
6unitsPage = requests.get(unitsUrl, headers=headers)
7
8
9# Obtain page's information
10
11unitsSoup = BeautifulSoup(unitsPage.text, 'html.parser')
12
13
14# Get the table by its id
15
16unitsTable = unitsSoup.find('table', {'id': 'ep538257'})
17
18
19# Transform the table into a list of dataframes
20
21unitsDf = pd.read_html(str(unitsTable))
Se examinarmos a tabela mais de perto, podemos ver que um dos valores está em branco. Embora faça sentido que o USPS inclua isso na tabela, não é algo que queremos em nossa lista de sinônimos. Tabela com descrições e abreviações do USPS Para resolver isso, removeremos todas as linhas com valores em branco:
1unitsDf[0] = unitsDf[0].dropna()
Em seguida, pegaremos nosso novo dataframe e o transformaremos em uma lista:
1# Create a 2D list that we will use for our synonyms
2
3unitsList = unitsDf[0][[0, 2]].values.tolist()
Você deve ter notado que alguns dos valores na tabela têm asteriscos. Vamos nos livrar rapidamente deles para que não sejam incluídos em nossos mapeamentos de sinônimos:
1# Remove all non-alphanumeric characters
2
3unitsList = [[re.sub("[^ \w]"," ",x).strip().lower() for x in y] for y in unitsList]
Agora podemos percorre-los e exportá-los como arquivos JSON individuais, como fizemos antes. A única coisa a observar é que queremos restringir o intervalo no qual estamos iterando para incluir apenas os dados relevantes que queremos:
1# Restrict the range to only retrieve the results we want
2
3for x in range(1, len(unitsList) - 1):
4
5
6    dictionary = {
7
8        "mappingType": "equivalent",
9
10        "synonyms": unitsList[x]
11
12    }
13
14
15    # export the JSON into a file
16
17    with open(unitsList[x][0] + ".json", "w") as outfile:
18
19        json.dump(dictionary, outfile)

Crie uma coleção de sinônimos com validação de JSON schema

Agora que criamos os documentos JSON para abreviações, vamos carregá-los todos em uma coleção no banco de dados sample_restaurants. Se você ainda não criou um cluster MongoDB, agora é um bom momento para fazer isso e carregar os dados de amostra.
O primeiro passo é conectar-se ao seu Atlas cluster. Usaremos o mongosh para fazer isso. Se você não tiver o mongosh instalado, siga as instruções.
Para se conectar ao Atlas cluster, você precisará de uma connection string. Escolha a opção "Connect with the MongoDB Shell " e siga as instruções. Observe que você precisará se conectar com um usuário do bancode dados que tenha permissões para modificar o banco de dados, pois criaremos uma coleção no banco de dados sample_restaurant. O comando que você precisa inserir no terminal será parecido com:
1mongosh "mongodb+srv://cluster0.XXXXX.mongodb.net/sample_restaurant" --apiVersion 1 --username <USERNAME>
Quando solicitado para a senha, digite a senha do usuário do banco de dados.
Criamos nossos documentos JSON sinônimos já no formato correto, mas vamos garantir que, se decidirmos adicionar mais documentos a essa collection, eles também terão o formato correto. Para fazer isso, criaremos uma collection de sinônimos com um validador que usa $jsonSchema. Os comandos abaixo criarão uma collection com o nome "postal_synonyms " no banco de dados sample_restaurants e garantirão que somente documentos com formato correto sejam inseridos na collection.
1use('sample_restaurants')
2
3db.createCollection("postal_synonyms", { validator: { $jsonSchema: { "bsonType": "object", "required": ["mappingType", "synonyms"], "properties": { "mappingType": { "type": "string", "enum": ["equivalent", "explicit"], "description": "must be a either equivalent or explicit" }, "synonyms": { "bsonType": "array", "items": { "type": "string" }, "description": "must be an Array with each item a string and is required" }, "input": { "type": "array", "items": { "type": "string" }, "description": "must be an Array and is each item is a string" } }, "anyOf": [{ "not": { "properties": { "mappingType": { "enum": ["explicit"] } }, "required": ["mappingType"] } }, { "required": ["input"] }] } } })

Importar os arquivos JSON para a collection de sinônimos

Usaremos o mongoimport para importar todos os arquivos JSON que criamos.
Você precisará de uma connection string para seu Atlas cluster usar no comando mongoimport. Se você ainda não tiver o mongoimport instalado, use as instruções na documentação do MongoDB.
No terminal, navegue até a pasta onde todos os arquivos JSON para sinônimos de abreviação postal foram criados.
1cat *.json | mongoimport --uri 'mongodb+srv://<USERNAME>:<PASSWORD>@cluster0.pwh9dzy.mongodb.net/sample_restaurants?retryWrites=true&w=majority' --collection='postal_synonyms'
Se você gostou do mongoimport, confira este guia muito útil do mongoimport.
Dê uma olhada nas coleções de sinônimos que você acabou de criar no Atlas. Você deve ver cerca de 229 documentos lá.
Documento com sinônimos postais na UI do Atlas

Crie um índice de pesquisa com mapeamento de sinônimos no Editor JSON

Agora que criamos a collection de sinônimos em nosso banco de dados sample_restaurants, vamos usá-la.
Vamos começar criando um índice de pesquisa. Navegue até a guia Pesquisar em seu cluster Atlas e clique no botão “CREATE INDEX”.
Como o Visual Index Builder ainda não oferece suporte a mapeamentos de sinônimos, escolheremos o JSON Editor e clicaremos em Next:
A IU Criar Índice de Pesquisa no Atlas No Editor JSON, escolha a coleção de restaurantes no banco de dados sample_restaurants e insira o seguinte na definição de índice. Aqui, o nome da coleção de origem refere-se ao nome da coleção com todos os sinônimos de abreviatura postal, que chamamos de "postal_synonyms."
1{
2
3  "mappings": {
4
5    "dynamic": true
6
7  },
8
9  "synonyms": [
10
11    {
12
13      "analyzer": "lucene.standard",
14
15      "name": "synonym_mapping",
16
17      "source": {
18
19        "collection": "postal_synonyms"
20
21      }
22
23    }
24
25    ]
26
27}
O Editor de IU do JSON do Criar Índice de Pesquisa no Atlas
Estamos indexando a collection de restaurantes e criando um mapeamento de sinônimos com o nome "synonym_mapping " que faz referência à collection de sinônimos "postal_synonyms. "
Clique em Avançar e, em seguida, em Criar índice de pesquisa, e aguarde a criação do índice de pesquisa.
Quando o índice estiver ativo, estamos prontos para testá-lo.

Teste se os sinônimos estão funcionando (pipeline de agregação no Atlas ou Compass)

Agora que temos um índice de pesquisa ativo, estamos prontos para testar se nossos sinônimos estão funcionando. Vamos até o pipeline de agregação na guia Coleções para testar diferentes chamadas para $search. Você também pode usar Compass, a interface do usuário do MongoDB, se preferir.
Escolha $search na lista de estágios do pipeline. A UI nos fornece um espaço reservado útil para os argumentos do comando $search.
Vamos procurar todos os restaurantes localizados em um bulevard. Vamos pesquisar no campo “address.street”, então os argumentos para o estágio $search ficarão assim:
1{
2
3  index: 'default',
4
5  text: {
6
7    query: 'boulevard',
8
9    path: 'address.street'
10
11  }
12
13}
Vamos adicionar um estágio $count após o estágio $search para ver quantos restaurantes com um endereço que contenha "boulevard " encontramos: Captura de tela mostrando os resultados de um pipeline de agregação com dois estágios e o termo de consulta "Boulevard". Como esperado, encontramos muitos restaurantes com a palavra “boulevard” no endereço. Mas e se não quisermos que os usuários digitem "boulevard " na barra de pesquisa? O que aconteceria se colocássemos "blvd, ", por exemplo?
1{
2
3  index: 'default',
4
5  text: {
6
7    query: blvd,
8
9    path: 'address.street'
10
11  }
12
13}
Captura de tela mostrando os resultados de um pipeline de agregação com dois estágios e termo de consulta "blvd". Parece que nos encontrou restaurantes com endereços que têm “blvd” neles. E os endereços com "boulevard, "? Esses não foram detectados pela busca. 
E se não tivéssemos certeza de como se escreve "boulevard " e apenas procurarmos "boul "? O site do USPS nos informa que é uma abreviação aceitável para Boulevard, mas nosso $search não encontra nada. Captura de tela mostrando os resultados de um pipeline de agregação com dois estágios e termo de consulta "boul". É aqui que entram os nossos sinônimos! Precisamos adicionar uma opção sinônimos ao operador de texto no comando $search e fazer referência ao nome do mapeamento de sinônimos:
1{
2
3  index: 'default',
4
5  text: {
6
7    query: 'blvd',
8
9    path: 'address.street',
10
11    synonyms:'synonym_mapping'
12
13  }
14
15}
Captura de tela mostrando os resultados de um pipeline de agregação com dois estágios, termo de consulta "boul" e sinônimos habilitados. E aqui está! Encontrámos todos os restaurantes em bulevards, independentemente de como o endereço foi abreviado, tudo graças aos nossos sinônimos.

Conclusão

O Synonyms é apenas um dos muitos recursos que o Atlas Search oferece para oferecer a você toda a funcionalidade de pesquisa necessária em seu aplicativo. Todas essas funcionalidades estão disponíveis agora no MongoDB Atlas. Acabamos de mostrar como adicionar suporte para abreviações postais comuns ao seu índice do Atlas Search — o que você pode fazer com o Atlas Search a seguir? Experimente agora em seu cluster MongoDB Atlas gratuito para sempre e acesse os fóruns da comunidade se tiver alguma dúvida!

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Início rápido

MongoDB com agente Bedrock: tutorial rápido


Jul 01, 2024 | 6 min read
Tutorial

Crie uma API CRUD com MongoDB, Typescript, Express, Prisma e Zod


Sep 04, 2024 | 10 min read
Artigo

Implantando o MongoDB Atlas com o Terraform com o Azure


Jun 18, 2024 | 7 min read
Artigo

Colocando o RAG em produção com o chatbot de IA da documentação do MongoDB


Aug 29, 2024 | 11 min read
Sumário