Index Mapping no Elasticsearch

Anselmo Borges
Rescue Point
Published in
8 min readDec 28, 2020
Dando aquela ajeitada nos seus index mappings

Primeiramente faz muito tempo que não posto materiais de Elastic por motivos pessoais e projetos em outras tecnologias, mas como acabei de montar um cluster novinho em folha pra um projeto, estou dando aquela ajeitada no index e esse material vai servir como base pra você que queira fazer isso.

Conteúdo em vídeo

Tem preguiça de ler? Eu te ajudo cara, segue um vídeo abaixo, mas é bem teórico, procure colocar em prática o material desse post, o vídeo tem 9 minutos é bem resumidinho.

Pra você que prefere ver e ouvir

Pra você que não conhece, o que é o Elasticsearch?

O Elasticsearch é uma ferramenta de busca, onde os dados estão armazenado em indices (que seriam databases em bancos de dados convencionais) e sua estrutura no formato chave/valor traz uma rapidez absurda em comparação a bancos de dados convencionais. O Elasticsearch é baseado no Apache Lucene e tem como concorrente direto o Splunk, que diferente do Elasticsearch, não é uma ferramenta que suporta alterações de dados (pelo menos não é essa a ideia dele), e foca nas consultas. Quando o Elasticsearch além de consultas rápidas dá a possibilidade de manipulação dos dados do índice.

O que é o Indice?

O índice é uma forma de centralizar os dados de acordo com tipo, assunto, aplicação ou como você achar melhor. Fazendo uma relação com bases de dados convencionais como MySQL, Oracle e outros, seria a grosso modo o database. Mas diferente dos databases onde criamos as tabelas, o índice já tem a estrutura de dados, por exemplo, um campo nome é texto, um campo data é data… e assim vai.

Mas não seria melhor comparar com uma tabela?

Ai que tá? Quando você fala de estrutura de dados no Elasticsearch que é baseada em chave/valor, bem JSON style, em um índice posso ter dados de várias tabelas, mas não necessariamente num processo inverso, o conteúdo de um índice eu conseguiria colocar numa única tabela… se liga.

Abaixo seriam as informações de uma tabela em um banco de dados convencional ou uma tabela de Excel por exemplo.

Exemplo de uma base de dados convencional

Nessa tabela que posso chamar de funcionários, cada linha é referente a um funcionário, a transformação disso pro formato do Elasticsearch seria:

Formato da tabela funcionarios

Note que cada linha no Elasticsearch vira um documento de ID único de cada um dos funcionários e agora finalmente vou chegar onde eu queria. Chamei o índice de funcionários, mas imagina se eu tivesse outras tabelas relacionadas ao funcionário, como endereço, outra de cursos, outra de comportamento por exemplo.

No Elasticsearch conseguiria reunir todas as informações de um funcionário numa única CAPIVARA, sem necessidade joins e merges.

Por isso prefiro comparar com um Database e não a uma tabela, pois eu posso ter dados de mais de uma tabela em um documento e o índice é o conjunto de documentos.

O que é SCHEMA?

Se você é como eu que veio do Oracle, vai entender que o Schema é estrutura de tabelas de um determinado dono (owner). Numa estrutura de base chave/valor, parquet, Avro, você vai entender que Schema não é nada disso nesse caso.

Schema é quando eu falo qual o tipo de dado de cada campo, por exemplo, nome é texto, data de nascimento é do tipo data, salário do tipo float e assim vai. Ai que entra o termo SCHEMA MAPPING que é o intuito desse post.

Porque dei essa volta toda pra chegar no Mapping?

Por que gosto de explicar tudo bem explicadinho… rs

Eu sei… me odeie…

Tipos de Index Mapping no Elasticsearch

Eu sempre vou comparar com o mundo do banco de dados relacional, pois a chance de você estar nesse post ter vindo desse mundo é muito grande e pra você que não é, acho uma analogia simples pra você também.

Os tipos de Mapping no ElasticSearch são:

  • Default Mapping
  • Custom Mapping

Default Mapping

Quero inserir um registro diretão via comando HTTP PUT no Elasticsearch, o índice nem existe ainda, você dá o nome do índice e manda o dado, se liga no exemplo abaixo:

PUT meu_index/_doc/1
{
"nome": "Adriana",
"sobrenome": "Moraes",
"data de admissão": "1997-08-10",
"profissão": "Engenheira",
"salário": 15000
}

O Elasticsearch automaticamente vai criar um índice chamado meu_index e para os campos como nome, sobrenome e profissão que coloquei as aspas e forcei como string (texto) ele vai fazer o mapping para “text” e “keyword”, no campo data de admissão claro que vai ser um date. E o salário ele vai setar como long.

Com o comando GET meu_index/_mapping conforme o exemplo abaixo, mostra como ficou o mapping desse index criado automaticamente.

GET meu_index/_mapping{
"meu_index" : {
"mappings" : {
"properties" : {
"data de admissão" : {
"type" : "date"
},
"nome" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"profissão" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"salário" : {
"type" : "long"
},
"sobrenome" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}

Então em poucas palavras, quando insiro os dados tanto em um índice existente como num inexistente ele cria indice e campos no formato que ele acha melhor, esse é o Default Mapping

Custom Mapping

Quando crio uma tabela no MySQL por exemplo, ela não tem dados, ou seja, eu crio a casca e depois coloco os dados. Na criação dessa tabela eu já defino qual o tipo de dado de cada uma das colunas e tal. O que o custom mapping faz é basicamente o mesmo, eu crio o índice e o mapping antes e depois insiro os dados.

Vou usar o mesmo exemplo do dado anterior e vou chamar de “meu_custom_index”.

PUT meu_custom_index
{
"mappings" : {
"properties" : {
"data de admissão" : {
"type" : "date",
"format": "dd-MM-yyyy"
},
"nome" : {
"type" : "keyword"
},
"profissão" : {
"type" : "keyword"
},
"salário" : {
"type" : "long"
},
"sobrenome" : {
"type" : "keyword"
}
}
}
}

Note que customizei o índice, alterando o formato da data pro nosso formato Brasil e os campos de text alterei pra que use somente o formato keyword para busca exata.

Agora basta inserir o mesmo registro nesse novo índice com o comando abaixo (só altero o formato da data na inserção também):

PUT meu_custom_index/_doc/1
{
"nome": "Adriana",
"sobrenome": "Moraes",
"data de admissão": "10-08-1997",
"profissão": "Engenheira",
"salário": 15000
}

Vamos ver agora como ficou:

GET meu_custom_index/_mapping{
"meu_custom_index" : {
"mappings" : {
"properties" : {
"data de admissão" : {
"type" : "date",
"format" : "dd-MM-yyyy"
},
"nome" : {
"type" : "keyword"
},
"profissão" : {
"type" : "keyword"
},
"salário" : {
"type" : "long"
},
"sobrenome" : {
"type" : "keyword"
}
}
}
}
}

Para ver o dado lá dentro do indice basta rodar o comando GET meu_custom_index/_search e todos os documentos do indice serão exibidos (nesse caso só os dados da Adriana).

GET meu_custom_index/_search{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "meu_custom_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"nome" : "Adriana",
"sobrenome" : "Moraes",
"data de admissão" : "10-08-1997",
"profissão" : "Engenheira",
"salário" : 15000
}

}
]
}
}

OBSERVAÇÃO IMPORTANTE

Os indices são imutáveis, ou seja, depois de criados não podem ser alterados, o máximo que pode acontecer é a criação de algum campo, mas não é possível alterar o tipo do dado nem remover um campo já existente.

Sempre quando necessário algo do tipo é feito um processo de reindex dos dados para um novo index alterado.

Adicionando novos campos a um índice

Funciona da mesma forma que o conceito de default e custom mapping, se você vai inserir um dado e esse campo não existe ele automaticamente vai escolher o formato desse dado como o default index, se liga só, vou inserir um segundo registro, com o campo “ativo”, um boolean para saber se ele está em atividade ou não, vou fazer isso no index recém criado com custom index “meu_custom_index”

PUT meu_custom_index/_doc/2
{
"nome": "Andreia",
"sobrenome": "Moraes",
"data de admissão": "22-07-2000",
"profissão": "Diretora",
"salário": "20000",
"ativo": "sim"
}

Mas se liga na merda, eu coloquei no ativo “sim/não” no boolean e não “true/false” como deveria ser, então com certeza esse campo foi criado com um formato text/keyword.

GET meu_custom_index/_mapping{
"meu_custom_index" : {
"mappings" : {
"properties" : {
"ativo" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
,
"data de admissão" : {
"type" : "date",
"format" : "dd-MM-yyyy"
},
"nome" : {
"type" : "keyword"
},
"profissão" : {
"type" : "keyword"
},
"salário" : {
"type" : "long"
},
"sobrenome" : {
"type" : "keyword"
}
}
}
}
}

Vou fazer a alteração no índice que foi criado inicialmente, inserindo o campo ativo no formato boolean.

PUT meu_index/_mapping
{
"properties": {
"ativo": {
"type": "boolean"

}
}
}

Vamos ver como está esse mapping agora:

{
"meu_index" : {
"mappings" : {
"properties" : {
"ativo" : {
"type" : "boolean"

},
"data de admissão" : {
"type" : "date"
},
... }
}
}
}
}
}
}

Agora vamos inserir o mesmo registro alterando o formato da data e o ativo pra true ao invés de “sim”.

PUT meu_index/_doc/2
{
"nome": "Andreia",
"sobrenome": "Moraes",
"data de admissão": "2000-07-20",
"profissão": "Diretora",
"salário": "20000",
"ativo": true
}

Pronto, sabemos criar indices customizados, default indexes, adicionar campos tanto de forma default ou customizadas.

Último aviso

O principal problema que tive no Elasticsearch nesse aspecto é:

Se o desenvolvedor não segue um padrão de nome de campos, sempre quando ele colocar um nome errado, por padrão ele vai aceitando e o índice fica um lixo, é horrível pra quando você vai fazer uma busca, pois não tem um padrão. Existe como criar um index com mapping customizado e bloquear esse índice para que nada fora os campos já existentes sejam criados nele.

Mas isso veremos em um próximo post, onde possivelmente explicarei como fazer um template index também, que permite que sempre que seja criado um campo atendendo uma serie definida de pré requisitos ele tenha um formato definido por você.

Se eu estiver animado faço esse post ainda hoje.

Espero que tenha ajudado.
Anselmo Borges.

--

--

Anselmo Borges
Rescue Point

Bigdata Engineer, Cloud Architect, Nerd, Alcoholic, Brazilian Jiujitsu Black belt and hide and seek World champion.