6 ‐ Index Settings: Entendendo Mapping, Analyzers e Aliases - BktechBrazil/elasticstacktotal GitHub Wiki
5.1 - Mapping
Importância e Benefícios:
O mapping no Elasticsearch define como os dados são armazenados e indexados. Uma configuração de mapping adequada permite que você otimize o armazenamento, melhore a performance das consultas e controle a análise de texto.
Exemplo de Uso:
PUT /clientes
{
"mappings": {
"properties": {
"nome": { "type": "text" },
"idade": { "type": "integer" },
"email": { "type": "keyword" }
}
}
}
Este exemplo define um índice clientes com campos específicos e tipos de dados definidos.
Dynamic Mapping:
O Elasticsearch pode inferir os tipos de dados dos campos durante a indexação. No entanto, para um controle mais refinado, é recomendável definir o mapping explicitamente.
Exemplo de Dynamic Mapping:
Se você não definir um mapping e indexar um documento, o Elasticsearch criará um mapping automaticamente.
POST /clientes/_doc/1
{
"nome": "Maria",
"idade": 28
}
Neste caso, o Elasticsearch inferirá nome como text e idade como integer.
Dynamic Templates:
Permitem definir regras de mapping para campos com base em padrões de nome, tipo ou outras condições.
Exemplo de Dynamic Template:
PUT /clientes
{
"mappings": {
"dynamic_templates": [
{
"strings_as_keywords": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
Este template trata todos os novos campos de string como keyword.
POST clientes/_doc/1
{
"frase": "Boa tarde a todos"
}
GET clientes/_mapping
Analisando o mapeamento do campo criado, observa-se que o dynamic template reconheceu o novo campo como string e o indexou como keyword.
Field Data Types:
Os tipos de dados de campo incluem text, keyword, date, integer, float, boolean e muitos outros.
Exemplo de Multi-Field:
PUT /clientes
{
"mappings": {
"properties": {
"nome": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
Neste exemplo, nome é indexado como text e como keyword no subcampo raw.
5.2 - Análise de Texto: Analysis, Analyzers, Tokenization e Normalizers
Analysis

A análise de texto no Elasticsearch é um processo fundamental que transforma texto bruto em termos ou tokens que podem ser indexados. Esse processo é composto por várias etapas, incluindo tokenização, filtragem de tokens, e, em alguns casos, normalização. A análise é essencial para realizar buscas eficientes em campos de texto, permitindo que o Elasticsearch entenda e compare os dados de texto.
Analyzers

Um analyzer no Elasticsearch é uma ferramenta que encapsula o processo de análise de texto, combinando três componentes principais: o tokenizer e, opcionalmente, vários token filters e character filters.
-
Tokenizers: Divide o texto em tokens (geralmente palavras). Por exemplo, o tokenizer
standarddivide o texto em palavras com base em certos critérios de separação, como espaços e pontuação. -
Token Filters: Processam a sequência de tokens gerados pelo tokenizer. Eles podem modificar, adicionar ou remover tokens. Exemplos incluem
lowercase(converte todos os tokens em letras minúsculas) estop(remove palavras comuns, também conhecidas como stopwords). -
Character Filters: Processam o texto antes da tokenização, permitindo a substituição ou remoção de caracteres. Por exemplo, um character filter pode remover HTML ou converter caracteres HTML em seus equivalentes de texto.
Exemplo de Analyzer:
GET /_analyze
{
"analyzer": "standard",
"text": "Text for analysis!"
}
Este exemplo demonstra como um texto será analisado usando o analyzer standard.
Tokenization
Tokenization é o processo de dividir o texto em uma série de tokens ou termos. É o primeiro passo crítico na análise de texto, pois determina a granularidade dos dados que serão indexados e pesquisados.
Exemplo de Tokenization:
POST /_analyze
{
"tokenizer": "standard",
"text": "Quick brown fox."
}
Este exemplo mostra como o texto será dividido em tokens usando o tokenizer standard.
Normalizers
Os normalizers são usados para campos do tipo keyword e aplicam uma transformação de normalização de texto. Diferentemente dos analyzers, que podem alterar o número de termos, os normalizers sempre produzem exatamente um termo por termo de entrada, sendo úteis para normalizar tokens para buscas consistentes, como converter textos para minúsculas.
Exemplo de Normalizer:
Suponha que você tenha definido um normalizer no seu mapping que converte texto para minúsculas:
PUT /meu_index
{
"settings": {
"analysis": {
"normalizer": {
"meu_normalizer": {
"type": "custom",
"char_filter": [],
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"meu_campo_keyword": {
"type": "keyword",
"normalizer": "meu_normalizer"
}
}
}
}
Este normalizer pode ser usado para garantir que todos os dados no campo meu_campo_keyword sejam armazenados em letras minúsculas.
POST meu_index/_doc/
{
"meu_campo_keyword": "BOA TARDE"
}
GET meu_index/_search
{
"size": 0,
"aggs": {
"my_aggs": {
"terms": {
"field": "meu_campo_keyword"
}
}
}
}
5.3 - Alias
Aliases e sua Aplicabilidade:
Um alias é um nome alternativo para um índice que pode ser usado para ocultar detalhes de implementação aos usuários ou aplicações.
Exemplo de Criação de Alias:
POST /_aliases
{
"actions": [
{
"add": {
"index": "clientes",
"alias": "clientes_atuais"
}
}
]
}
Agora, clientes_atuais pode ser usado no lugar do nome do índice clientes.
Aliases com Filtros:
Exemplo de Alias com Filtro:
POST /_aliases
{
"actions": [
{
"add": {
"index": "clientes",
"alias": "clientes_adultos",
"filter": { "range": { "idade": { "gte": 18 } } }
}
}
]
}
Este alias clientes_adultos só expõe documentos de clientes com 18 anos ou mais.
5.4 - Laboratório 1: Criando um Índice com Mapeamento Específico no Elasticsearch
Neste laboratório, vamos criar um índice no Elasticsearch chamado clientes com um mapeamento específico para os campos codigo, nome, sexo, estado_civil, data_nascimento e caracteristicas. Além disso, configuraremos um mapeamento dinâmico para campos com o prefixo logradouro para serem tratados como keyword.
Etapa 1: Criar o Índice com Mapeamento
- Definir o Índice e o Mapeamento:
PUT /clientes
{
"mappings": {
"dynamic_templates": [
{
"logradouros_as_keywords": {
"match_mapping_type": "string",
"match_pattern": "regex",
"match": "^logradouro.*",
"mapping": {
"type": "keyword"
}
}
}
],
"properties": {
"codigo": {
"type": "integer"
},
"nome": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"sexo": {
"type": "keyword"
},
"estado_civil": {
"type": "keyword"
},
"data_nascimento": {
"type": "date"
},
"caracteristicas": {
"type": "text"
}
}
}
}
Explicação:
codigo: Campo do tipointeger.nome: Campo do tipotextcom um subcampokeywordpara permitir buscas exatas e baseadas em texto.sexoeestado_civil: Campos do tipokeywordpara buscas exatas.data_nascimento: Campo do tipodatepara armazenar datas.caracteristicas: Campo do tipotextpara armazenar texto livre.dynamic_templates: Template dinâmico que aplica o tipokeyworda qualquer campo que comece comlogradouro.
Etapa 2: Indexando Documentos de Exemplo
Agora, vamos indexar um documento de exemplo para ver o mapeamento em ação.
POST /clientes/_doc/1
{
"codigo": 123,
"nome": "João Silva",
"sexo": "masculino",
"estado_civil": "casado",
"data_nascimento": "1980-05-15",
"caracteristicas": "Amigável, extrovertido, atencioso",
"logradouro_principal": "Rua das Flores",
"logradouro_secundario": "Avenida das Árvores"
}
Neste exemplo, os campos logradouro_principal e logradouro_secundario são tratados como keyword devido ao nosso mapeamento dinâmico.
Etapa 3: Validando o Mapeamento
Você pode verificar o mapeamento efetivo usando a seguinte chamada API:
GET /clientes/_mapping
Essa chamada retornará o mapeamento atual do índice clientes, permitindo que você confirme se todos os campos estão configurados conforme desejado.
Etapa 4: Acrescentando Parâmetro Dynamic no Mapeamento
O parâmetro dynamic no mapeamento do Elasticsearch controla como os campos não especificados no mapeamento são tratados quando novos documentos são indexados. Ele pode ter três valores: true, false e strict.
-
Dynamic: true
Este é o valor padrão. Quando
dynamicestá configurado comotrue, o Elasticsearch detecta automaticamente os tipos de campo dos campos não mapeados e os adiciona ao mapeamento.Exemplo:
Se indexarmos um novo documento com um campo não definido no mapeamento, como
novo_campo, o Elasticsearch adicionará automaticamentenovo_campoao mapeamento com um tipo inferido. -
Dynamic: false
Quando configurado como
false, o Elasticsearch não adicionará novos campos ao mapeamento. Os campos não mapeados serão aceitos e indexados, mas não serão pesquisáveis.Exemplo de Mapeamento com Dynamic False:
PUT /clientes { "mappings": { "dynamic": "false", "dynamic_templates": [ { "logradouros_as_keywords": { "match_mapping_type": "string", "match_pattern": "regex", "match": "^logradouro.*", "mapping": { "type": "keyword" } } } ], "properties": { "codigo": { "type": "integer" } // outros campos mapeados } } }Se indexarmos um documento com um campo que não esteja no mapeamento, esse campo será armazenado, mas não será adicionado ao mapeamento.
-
Dynamic: strict
Se
dynamicfor configurado comostrict, o Elasticsearch rejeitará documentos que contêm campos não mapeados, retornando um erro.Exemplo de Mapeamento com Dynamic Strict:
PUT /clientes { "mappings": { "dynamic": "strict", "dynamic_templates": [ { "logradouros_as_keywords": { "match_mapping_type": "string", "match_pattern": "regex", "match": "^logradouro.*", "mapping": { "type": "keyword" } } } ], "properties": { "codigo": { "type": "integer" } // outros campos mapeados } } }Nesse caso, se tentarmos indexar um documento com um campo que não esteja no mapeamento, receberemos um erro.
Ao definir dynamic como strict, o Elasticsearch garantirá que somente os campos definidos no mapeamento possam ser indexados, oferecendo um controle estrito sobre a estrutura dos dados no índice.
5.5 - Laboratório 2 - Customizando Analysis e Analyzers
Neste laboratório, vamos aprender a customizar um analyzer no Elasticsearch usando o tokenizer edge_ngram. Vamos aplicar isso no contexto de um índice chamado fornecedor, focando na tokenização do campo nome_fornecedor para aprimorar as buscas.
Passo 1: Criando o Índice com Analyzer Customizado
-
Defina o índice
fornecedorcom o analyzer customizado:PUT /fornecedor { "settings": { "analysis": { "analyzer": { "my_analyzer_ngram_3": { "tokenizer": "split_3_ngram" } }, "tokenizer": { "split_3_ngram": { "type": "edge_ngram", "min_gram": 3, "max_gram": 15, "token_chars": [ "letter", "digit" ] } } } }, "mappings": { "properties": { "codigo": { "type": "integer" }, "nome_fornecedor": { "type": "text", "fields": { "keyword": { "type": "keyword" } } }, "nome_fornecedor_engram": { "type": "text", "analyzer": "my_analyzer_ngram_3", "search_analyzer": "my_analyzer_ngram_3", "fields": { "keyword": { "type": "keyword" } } }, "cnpj": { "type": "keyword" }, "endereco": { "type": "keyword" }, "bairro": { "type": "keyword" }, "cidade": { "type": "keyword" }, "uf": { "type": "keyword" } } } }Aqui, criamos um tokenizer
edge_ngramchamadosplit_3_ngram, que gera tokens com um comprimento de 3 a 15 caracteres. Este tokenizer é usado no analyzermy_analyzer_ngram_3, que é aplicado ao camponome_fornecedor_engram.
Passo 2: Testando o Tokenizer
Para entender como o texto será tokenizado, você pode usar o seguinte comando:
POST fornecedor/_analyze
{
"tokenizer": "split_3_ngram",
"text": "GOLLINHASAEREAS"
}
Esse comando irá demonstrar como o texto "GOLLINHASAEREAS" será dividido em tokens pelo tokenizer customizado my_analyzer_ngram_3.
Passo 3: Inserindo Documentos para Teste
-
Insira o primeiro documento:
POST /fornecedor/_doc/1 { "codigo": 124, "nome_fornecedor": "GOL Linhas Aereas", "nome_fornecedor_engram": "GOL Linhas Aereas", "cnpj": "12222334000102", "endereco": "Rua tal e etc", "bairro": "Fulano", "cidade": "Caxias", "uf": "RJ" } -
Insira o segundo documento:
POST /fornecedor/_doc/1 { "codigo": 124, "nome_fornecedor": "TAM Linhas Aereas", "nome_fornecedor_engram": "TAM Linhas Aereas", "cnpj": "12222334000102", "endereco": "Rua tal e etc", "bairro": "Fulano", "cidade": "Caxias", "uf": "RJ" }
Passo 4: Realizando uma Busca
Agora, vamos realizar uma busca para verificar a eficácia do nosso analyzer:
GET fornecedor/_search
{
"query": {
"match": {
"nome_fornecedor_engram": "TAMLINHASAEREAS"
}
}
}
Nessa busca, estamos procurando por "TAMLINHASAEREAS" no campo nome_fornecedor_engram. Graças ao nosso analyzer customizado, mesmo que não haja uma correspondência exata, a busca será capaz de encontrar "TAM Linhas Aereas" graças à tokenização feita pelo edge_ngram.
Conclusão
Neste laboratório, você aprendeu a criar um analyzer customizado usando edge_ngram no Elasticsearch, aplicá-lo a um campo específico e testar sua funcionalidade. Além disso, você viu como inserir dados e realizar uma busca efetiva utilizando o analyzer customizado para melhorar a relevância dos resultados.
5.6 - Laboratório 3 - Criando Aliases de Índices
Neste laboratório, aprenderemos a unificar e organizar o acesso a múltiplos índices no Elasticsearch usando aliases. Primeiramente, criaremos dois índices, fornecedor_matriz e fornecedor_filial, e depois configuraremos aliases para unificá-los e criar uma visão filtrada.
Passo 1: Criação dos Índices
-
Crie o índice
fornecedor_matriz:PUT /fornecedor_matriz { "mappings": { "properties": { "codigo": { "type": "integer" }, "nome_fornecedor": { "type": "text", "fields": { "keyword": { "type": "keyword" } } }, "cnpj": { "type": "keyword" }, "endereco": { "type": "keyword" }, "bairro": { "type": "keyword" }, "cidade": { "type": "keyword" }, "uf": { "type": "keyword" } } } } -
Crie o índice
fornecedor_filial:PUT /fornecedor_filial { "mappings": { "properties": { "codigo": { "type": "integer" }, "nome_fornecedor": { "type": "text", "fields": { "keyword": { "type": "keyword" } } }, "cnpj": { "type": "keyword" }, "endereco": { "type": "keyword" }, "bairro": { "type": "keyword" }, "cidade": { "type": "keyword" }, "uf": { "type": "keyword" } } } }
Passo 2: Inserindo Documentos nos Índices
-
Insira um documento no
fornecedor_matriz:POST /fornecedor_matriz/_doc/1 { "codigo": 124, "nome_fornecedor": "TAM Linhas Aereas", "cnpj": "12222334000102", "endereco": "Rua tal e etc", "bairro": "Fulano", "cidade": "Caxias", "uf": "RJ" } -
Insira um documento no
fornecedor_filial:POST /fornecedor_filial/_doc/1 { "codigo": 124, "nome_fornecedor": "GOL Linhas Aereas", "cnpj": "12222334000102", "endereco": "Rua tal e etc", "bairro": "Fulano", "cidade": "Santos", "uf": "SP" }
Passo 3: Criando o Alias "corporacao"
-
Configure o alias
corporacaopara unificar os dois índices:POST _aliases { "actions": [ { "add": { "index": "fornecedor_matriz", "alias": "corporacao" } }, { "add": { "index": "fornecedor_filial", "alias": "corporacao" } } ] } -
Teste a busca pelo alias
corporacao:GET corporacao/_searchEssa busca retornará resultados de ambos os índices,
fornecedor_matrizefornecedor_filial.
Passo 4: Criando um Alias Filtrado "fornecedores_sp"
-
Crie um alias
fornecedores_spcom um filtro para a UF "SP":POST _aliases { "actions": [ { "add": { "index": "fornecedor_*", "alias": "fornecedores_sp", "filter": { "term": { "uf": "SP" } } } } ] } -
Realize uma consulta pelo alias
fornecedores_sp:GET fornecedores_sp/_searchA consulta retornará apenas os documentos do estado de São Paulo.
Conclusão
Você aprendeu a criar e configurar aliases para unificar o acesso a múltiplos índices no Elasticsearch, além de poder restringir o acesso a informações especificas de determinados índices. Com o alias, também é possível aplicar o versionamento de um índice sem que o seu nome original seja alterado.
5.7 - Laboratório 4 - Aplicando todas as configurações de índice de uma só vez
Neste laboratório, aprenderemos a configurar todos os parâmetros vistos nessa aula de uma só vez. Adicionalmente, vamos atrelar a essas configurações uma política de ILM para entendermos que também podemos definir tudo isso no momento da criação do índice. Primeiro, vamos criar a política que queremos atrelar aos índices em questão; depois, criaremos o que chamamos de componente template, além de atrelar ele a um index template. Por fim, faremos um bulk em dois índices para verificar as configurações feitas.
Passo 1: Criação da política de ILM
-
Definir a política
policy_pessoas:PUT _ilm/policy/policy_pessoas { "policy": { "phases": { "hot": { "actions": { } }, "warm": { "min_age": "1d", "actions": { "forcemerge": { "max_num_segments": 1 } } }, "cold": { "min_age": "7d", "actions": { "freeze": {} } }, "delete": { "min_age": "30d", "actions": { "delete": {} } } } } }
Passo 2: Criação do component template
Vamos criar o component template a atrelar às novas configurações a ILM Policy.
-
Definir o component template
ct_pessoas:PUT _component_template/ct_pessoas { "template": { "settings": { "number_of_shards": 1, "number_of_replicas": 1, "index.lifecycle.name": "policy_pessoas" }, "mappings": { "properties": { "nome": { "type": "text" }, "idade": { "type": "integer" }, "sexo": { "type": "keyword" }, "uf": { "type": "keyword" } } }, "aliases": { "pessoas": {} } } }
Passo 3: Criação do index template
Nesta etapa vamos criar o template do índice contendo todas as informações que criamos e vamos também atrelar um padrão de nome para os índices se associarem a esse template.
-
Definir o index template
it_pessoas:PUT _index_template/it_pessoas { "index_patterns": ["pessoas_*"], "composed_of": ["ct_pessoas"] }
Passo 4: Indexar documentos de exemplo
-
Indexar documentos no índice
pessoas_rj:POST /_bulk { "index" : { "_index" : "pessoas_rj", "_id" : "1" } } { "nome" : "João da Silva", "sexo" : "masculino", "idade" : 19, "uf" : "RJ" } { "index" : { "_index" : "pessoas_rj", "_id" : "2" } } { "nome" : "Maria Oliveira", "sexo" : "feminino", "idade" : 28, "uf" : "RJ" } { "index" : { "_index" : "pessoas_rj", "_id" : "3" } } { "nome" : "Roberto Carlos", "sexo" : "masculino", "idade" : 35, "uf" : "RJ" } { "index" : { "_index" : "pessoas_rj", "_id" : "4" } } { "nome" : "Ana Maria", "sexo" : "feminino", "idade" : 14, "uf" : "RJ" } { "index" : { "_index" : "pessoas_rj", "_id" : "5" } } { "nome" : "Paulo Souza", "sexo" : "masculino", "idade" : 15, "uf" : "RJ" } -
Indexar documentos no índice
pessoas_sp:POST /_bulk { "index" : { "_index" : "pessoas_sp", "_id" : "1" } } { "nome" : "Bruno Garcia", "sexo" : "masculino", "idade" : 22, "uf" : "SP" } { "index" : { "_index" : "pessoas_sp", "_id" : "2" } } { "nome" : "Renata Santos", "sexo" : "feminino", "idade" : 30, "uf" : "SP" } { "index" : { "_index" : "pessoas_sp", "_id" : "3" } } { "nome" : "Gilberto Ferreira", "sexo" : "masculino", "idade" : 48, "uf" : "SP" } { "index" : { "_index" : "pessoas_sp", "_id" : "4" } } { "nome" : "Maria Silva", "sexo" : "feminino", "idade" : 12, "uf" : "SP" } { "index" : { "_index" : "pessoas_sp", "_id" : "5" } } { "nome" : "Pedro Borges", "sexo" : "masculino", "idade" : 15, "uf" : "SP" }
Passo 5: Verificar indexação e aplicação das configurações
GET pessoas_rj
GET pessoas_sp
GET pessoas/_search
Conclusão
Você aprendeu a aplicar todas as configurações vistas nessa página em poucas operações. Configuramos uma política de ILM, atrelamos essa política a um component template onde adicionamos configurações do índice e mapeamento dos campos esperados; após isso, associamos essas criações a um template de índice, que ficou responsável por encontrar novos índices que atendesse aos critérios passados e aplicasse neles as configurações criadas.