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
MongoDBchevron-right

Queries que não diferenciam maiúsculas de minúsculas sem índices que não diferenciam maiúsculas de minúsculas

Lauren Schaefer, Daniel Coupal8 min read • Published Feb 12, 2022 • Updated Oct 01, 2024
MongoDBEsquema
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Começamos o sexto e último (pelo menos por enquanto) antipadrão de projeto de esquema do MongoDB. Nas primeiras cinco publicações desta série, abordamos os seguintes antipadrões.
Hoje, exploraremos o maravilhoso mundo dos índices que não diferenciam maiúsculas de minúsculas. Não ter um índice que não diferencia maiúsculas de minúsculas pode gerar resultados surpreendentes de queries e/ou queries lentas... e fazer com que você odeie tudo.
Ron Swanson diz "Eu odeio tudo"
Depois de saber melhor como as queries que diferenciam maiúsculas de minúsculas funcionam, a implementação é bastante simples. Vamos nessa!
Assista ao vídeo acima para ver as queries e os índices que não diferenciam maiúsculas de minúsculas em ação.

Queries que não diferenciam maiúsculas de minúsculas sem índices que não diferenciam maiúsculas de minúsculas

O MongoDB permite três maneiras principais de executar queries que não diferenciam maiúsculas de minúsculas.
Primeiro, você pode executar uma query que não diferencia maiúsculas de minúsculas usando $regex com a opção i. Essas queries fornecerão os resultados esperados que não diferenciam maiúsculas de minúsculas. No entanto, as queries que usam $regex não lidam bem com índices que não diferenciam maiúsculas de minúsculas, então essas queries podem ser muito lentas dependendo da quantidade de dados na sua coleção.
Em segundo lugar, você pode executar uma query que não diferencia maiúsculas de minúsculas criando um índice (o que significa que ele tem uma intensidade de agrupamento de 1 ou 2) e executando uma query com o mesmo agrupamento do índice. Um agrupamento define as regras específicas da linguagem que o MongoDB usará para comparação de string. Opcionalmente, os índices podem ter um agrupamento com uma intensidade que varia de 1 a 5. As intensidades de 1 e de agrupamento 2 garantem diferenciação entre maiúsculas e minúsculas. Para obter mais informações sobre as diferenças das intensidades de agrupamento, consulte a documentação do MongoDB . Uma query executada com o mesmo agrupamento de um índice que não diferencia maiúsculas de minúsculas retornará resultados que não diferenciam maiúsculas de minúsculas. Como essas queries são abrangidas por índices, elas são executadas muito rapidamente.
A terceira opção é executar uma query que diferencia maiúsculas de minúsculas definindo a intensidade de agrupamento padrão para queries e índices como uma intensidade de 1 ou 2 ao criar uma coleção. Todas as queries e índices em uma coleção usam automaticamente o agrupamento padrão, a menos que você especifique algo diferente disso ao executar uma query ou criar um índice. Portanto, ao definir o agrupamento padrão com uma intensidade de 1 ou 2, você obterá queries e índices que diferenciam maiúsculas de minúsculas por padrão. Consulte a opção collation na seção db.createCollection() da documentação do MongoDB para saber mais informações.
Aviso para queries que não usam $regex: seu índice deve ter uma intensidade de agrupamento de 1 ou 2 e sua query deve usar o mesmo agrupamento que o índice para que a query não diferencie maiúsculas de minúsculas.
Você pode usar o MongoDB Compass (interface de usuário da versão desktop do MongoDB) ou o MongoDB Shell (a ferramenta de linha de comando do MongoDB) para testar se uma query está retornando os resultados esperados, ver seu tempo de execução e determinar se está usando um índice.

Exemplo

Vamos voltar para o exemplo que vimos nas publicações Antipadrões de índices desnecessários e Antipadrões de documentos volumosos. Leslie está criando um site que apresenta com mulheres inspiradoras. Ela criou um banco de dados com informações sobre mais de 4.700mulheres inspiradoras. Abaixo estão três documentos em sua coleção InspirationalWomen.
1{
2 "_id": ObjectId("5ef20c5c7ff4160ed48d8f83"),
3 "first_name": "Harriet",
4 "last_name": "Tubman",
5 "quote": "I was the conductor of the Underground Railroad for eight years,
6 and I can say what most conductors can't say; I never ran my
7 train off the track and I never lost a passenger"
8},
9{
10 "_id": ObjectId("5ef20c797ff4160ed48d90ea"),
11 "first_name": "HARRIET",
12 "middle_name": "BEECHER",
13 "last_name": "STOWE",
14 "quote": "When you get into a tight place and everything goes against you,
15 till it seems as though you could not hang on a minute longer,
16 never give up then, for that is just the place and time that
17 the tide will turn."
18},
19{
20 "_id": ObjectId("5ef20c937ff4160ed48d9201"),
21 "first_name": "Bella",
22 "last_name": "Abzug",
23 "quote": "This woman's place is in the House—the House of Representatives."
24}
A Leslie decide adicionar um recurso de pesquisa ao seu site, porque está difícil navegar nele. Ela começa a implementar o recurso de pesquisa criando um índice no campo first_name. Em seguida, ela começa a testar uma query que buscará mulheres chamadas "Harriet".
A Leslie executa a seguinte query no MongoDB Shell:
1db.InspirationalWomen.find({first_name: "Harriet"})
Ela fica surpresa que a query retorna apenas um documento, porque tem duas Harriets em seu banco de dados: Harriet Tubman e Harriet Beecher Stowe. Então ela percebe que o nome de Harriet Beecher Stowe foi inserido todo em letras maiúsculas no banco de dados. Sua query diferencia maiúsculas de minúsculas, porque não está usando um índice sem distinção de maiúsculas e minúsculas.
Leslie executa a mesma query com .explain("executionStats") para ver o que está acontecendo.
1db.InspirationalWomen.find({first_name: "Harriet"}).explain("executionStats")
O Shell retorna a seguinte saída.
1{
2 "queryPlanner": {
3 ...
4 "winningPlan": {
5 "stage": "FETCH",
6 "inputStage": {
7 "stage": "IXSCAN",
8 "keyPattern": {
9 "first_name": 1
10 },
11 "indexName": "first_name_1",
12 ...
13 "indexBounds": {
14 "first_name": [
15 "[\"Harriet\", \"Harriet\"]"
16 ]
17 }
18 }
19 },
20 "rejectedPlans": []
21 },
22 "executionStats": {
23 "executionSuccess": true,
24 "nReturned": 1,
25 "executionTimeMillis": 0,
26 "totalKeysExamined": 1,
27 "totalDocsExamined": 1,
28 "executionStages": {
29 ...
30 }
31 }
32 },
33 ...
34}
Ela pode ver que winningPlan está usando um IXSCAN (verificação de índice) com seu índice first_name_1. Em executionStats, ela vê que apenas uma chave de índice foi analisada (executionStats.totalKeysExamined) e apenas um documento foi analisado (executionStats.totalDocsExamined). Para obter mais informações sobre como interpretar a saída de .explain(), consulte Analisar o desempenho da query.
Leslie abre o Compass e vê resultados semelhantes.
O MongoDB Compass mostra que a query está examinando apenas uma chave de índice, examinando apenas um documento e retornando apenas um documento. Isso também mostra que a query usou o índice first_name_1 .
O MongoDB Compass mostra que a query está examinando apenas uma chave de índice, examinando apenas um documento e retornando apenas um documento. E também mostra que a query utilizou o índice first_name_1.
Leslie quer que todas as Harriets (independentemente de estar escrito com letra maiúscula ou minúscula) sejam retornadas em sua query. Ela atualiza sua query para usar $regex com a opção i para indicar que a expressão regular deve diferenciar maiúsculas de minúsculas. Ela retorna ao Shell e executa sua nova query:
1db.InspirationalWomen.find({first_name: { $regex: /Harriet/i} })
Desta vez, ela obtém os resultados que esperava: os documentos de Harriet Tubman e também de Harriet Beecher Stowe. Leslie fica muito feliz! Ela executa a query novamente com .explain("executionStats") para obter detalhes sobre a execução da query. Veja abaixo o que o Shell retorna:
1{
2 "queryPlanner": {
3 ...
4 "winningPlan": {
5 "stage": "FETCH",
6 "inputStage": {
7 "stage": "IXSCAN",
8 "filter": {
9 "first_name": {
10 "$regex": "Harriet",
11 "$options": "i"
12 }
13 },
14 "keyPattern": {
15 "first_name": 1
16 },
17 "indexName": "first_name_1",
18 ...
19 "indexBounds": {
20 "first_name": [
21 "[\"\", {})",
22 "[/Harriet/i, /Harriet/i]"
23 ]
24 }
25 }
26 },
27 "rejectedPlans": []
28 },
29 "executionStats": {
30 "executionSuccess": true,
31 "nReturned": 2,
32 "executionTimeMillis": 3,
33 "totalKeysExamined": 4704,
34 "totalDocsExamined": 2,
35 "executionStages": {
36 ...
37 }
38 },
39 ...
40}
Ela pode ver que esta query, como a anterior, usa um índice (IXSCAN). No entanto, como as queries $regex não podem utilizar eficientemente índices que não diferenciam maiúsculas de minúsculas, ela não está obtendo os benefícios típicos de uma query coberta por um índice. Todas as 4.704 chaves de índice (executionStats.totalKeysExamined) estão sendo examinadas como parte desta query, resultando em uma query um pouco mais lenta (executionStats.executionTimeMillis: 3) do que aquela que utiliza totalmente um índice.
Ela executa a mesma query no Compass e vê resultados semelhantes. A query está usando seu índice first_name_1, mas examinando cada chave de índice.
O MongoDB Compass mostra que a query está retornando dois documentos, conforme esperado. A query $regex está usando o índice first_name_1, mas examinando cada chave de índice.
O MongoDB Compass mostra que a query está retornando dois documentos, conforme esperado. A query $regex está usando o índice first_name_1, mas examinando cada chave de índice.
Leslie quer garantir que seu recurso de pesquisa seja executado o mais rápido possível. Ela usa o Compass para criar um novo índice que não diferencia maiúsculas de minúsculas chamado first_name-case_insensitive. E ela pode criar índices com facilidade usando outras ferramentas, como o Shell ou o MongoDB Atlas ou até mesmo pelo código de programação. O índice dela estará no campo first_name em ordem crescente e usará um agrupamento personalizado com um locale en e uma intensidade de 2. Lembre-se, como vimos na seção anterior, que a intensidade do agrupamento deve ser definida como 1 ou 2 para que o índice não diferencie maiúsculas de minúsculas.
Criando um novo índice no MongoDB Compass com um agrupamento personalizado que tenha um locale en e uma intensidade de 2.
Criando um novo índice no MongoDB Compass com um agrupamento personalizado que tenha um locale de en e uma intensidade de 2.
Leslie executa uma query muito semelhante à sua query original no Shell, mas desta vez ela especifica o agrupamento que corresponde ao índice recém-criado:
1db.InspirationalWomen.find({first_name: "Harriet"}).collation( { locale: 'en', strength: 2 } )
Desta vez, os resultados mostram tanto Harriet Tubman quanto Harriet Beecher Stowe. Sucesso!
Ela executa a query com .explain("executionStats") para garantir que a query esteja usando seu índice:
1db.InspirationalWomen.find({first_name: "Harriet"}).collation( { locale: 'en', strength: 2 } ).explain("executionStats")
O Shell retorna os seguintes resultados.
1{
2 "queryPlanner": {
3 ...
4 "collation": {
5 "locale": "en",
6 ...
7 "strength": 2,
8 ...
9 },
10 "winningPlan": {
11 "stage": "FETCH",
12 "inputStage": {
13 "stage": "IXSCAN",
14 "keyPattern": {
15 "first_name": 1
16 },
17 "indexName": "first_name-case_insensitive",
18 "collation": {
19 "locale": "en",
20 ...
21 "strength": 2,
22 ...
23 },
24 ...
25 "indexBounds": {
26 "first_name": [
27 "[\"7)KK91O\u0001\u000b\", \"7)KK91O\u0001\u000b\"]"
28 ]
29 }
30 }
31 },
32 "rejectedPlans": []
33 },
34 "executionStats": {
35 "executionSuccess": true,
36 "nReturned": 2,
37 "executionTimeMillis": 0,
38 "totalKeysExamined": 2,
39 "totalDocsExamined": 2,
40 "executionStages": {
41 ...
42 }
43 }
44 },
45 ...
46}
Leslie nota que a opção de sucesso é executar um IXSCAN (verificação de índice) que usa o índice que não diferencia maiúsculas de minúsculas que ela acabou de criar. Duas chaves de índice (executionStats.totalKeysExamined) estão sendo examinadas e dois documentos (executionStats.totalDocsExamined) estão sendo examinados. A query está sendo executada em 0 ms (executionStats.executionTimeMillis: 0). Isso é muito rápido!
Leslie executa a mesma query no Compass e especifica o agrupamento que a query deve usar.
Query com agrupamento no Compass.
Ela pode ver que a query está usando seu índice que não diferencia maiúsculas de minúsculas e está sendo executada em 0 ms. Ela está pronta para implementar seu recurso de pesquisa. É hora de comemorar!
Leslie dança.
Observação: outra opção para Leslie teria sido definir a força de agrupamento padrão de sua coleção "mulheres inspiradoras" como 1 ou 2 quando ela criou a coleção. Em seguida, todas as suas queries teriam retornado os resultados esperados, sem distinção de maiúsculas e minúsculas, independentemente de ela ter criado um índice ou não. Ela ainda gostaria de criar índices para aumentar o desempenho de suas queries.

Resumo

Você tem três opções principais quando deseja executar uma query sem diferenciar maiúsculas de minúsculas:
  1. Use $regex com a opção i. Mas saiba que essa opção não tem um desempenho tão bom, porque $regex não pode utilizar totalmente os índices que não diferenciam maiúsculas de minúsculas.
  2. Crie um índice que não diferencie maiúsculas de minúsculas com uma força de agrupamento de 1 ou 2 e especifique que sua query use o mesmo agrupamento.
  3. Defina a força de agrupamento padrão da sua coleção como 1 ou 2 ao criá-la e não especifique um agrupamento diferente em suas queries e índices.
Outra opção é usar o MongoDB Atlas Search para pesquisas de texto mais complexas.
Esta publicação é último antipadrão que abordaremos nesta série. Mas não precisa ficar triste, esta não é a última publicação da série. Aguarde a próxima publicação, em que resumiremos todos os antipadrões e mostraremos um novo recurso do MongoDB Atlas que ajudará a descobrir antipadrões em seu banco de dados. Não perca!
Quando estiver pronto para criar um esquema no MongoDB, confira o MongoDB Atlas, o banco de dados como serviço totalmente gerenciado do MongoDB. O Atlas é a maneira mais fácil de começar a usar o MongoDB e tem uma camada rica e gratuita para sempre.
Confira os seguintes recursos para obter mais informações:

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
{Parte de uma série
Antipadrões de projeto de esquema do MongoDB
Próximo
Continuar

Mais nesta série
Relacionado
Início rápido

Início rápido: tipos de dados BSON - Data


Sep 23, 2022 | 2 min read
Artigo

Estruturando dados com Serde em Rust


Apr 23, 2024 | 5 min read
Tutorial

Construindo com padrões: o padrão bucket


May 16, 2022 | 3 min read
Tutorial

Criptografia no nível do campo do lado do cliente (CSFLE) no MongoDB com Golang


Feb 03, 2023 | 15 min read
Sumário