Comparando: Elasticsearch vs MongoDB

Saiba as principais diferenças e semelhanças entre os dois, quando e como utilizá-los na arquitetura das suas aplicações

Vinícius Coimbra
Data Hackers
12 min readFeb 13, 2018

--

Há alguns meses, tenho ouvido com certa frequência de amigos desenvolvedores e até mesmo dentro da MaxMilhas, questionamentos sobre a utilização do Elasticsearch em função do MongoDB e vice-versa. A pergunta que mais ouço deles ultimamente é: “Qual dos dois eu tenho que usar: Elasticsearch ou MongoDB?”.

Tendo recebido tantas dúvidas sobre o mesmo tema, resolvi dar “uma geral” sobre o assunto, passando pelas principais semelhanças e diferenças entre essas duas incríveis ferramentas, elucidando um pouco sobre a arquitetura das duas e sobre onde e como deve-se usar.

As principais semelhanças entre Elasticsearch e MongoDB

Escaláveis e populares

Tanto o MongoDB quanto o Elasticsearch nasceram com premissas de terem uma alta capacidade de disponibilidade, escalabilidade, resiliência.

Tendo isto em mente, os dois cumprem muito bem o papel, utilizando ainda da sua facilidade de instalar (sendo boa parte “plug and play”).

Não é à toa que os dois estão nos TOP 10 bancos de dados mais utilizados no mundo de acordo com a DB-Engines, sendo cada um o primeiro de sua categoria (MongoDB para Document-Store e o Elasticsearch para Search-Engine).

Schema-free

Segundo a abordagem do “three-schema”, os dois, tanto Elasticsearch, quanto o MongoDB são considerados schema-free, ou seja, são bases de dados que não é necessário ter uma estrutura prevista para ter os dados inseridos, diferentemente dos bancos de dados tradicionais (MySQL, SQLServer, Oracle, PostgreSQL, etc.), onde você precisa definir a estrutura da tabela antes de inserir os dados.

Por terem a facilidade de mexerem com documentos em JSON que podem ser altamente mutáveis e fracamente tipados,dão uma flexibilidade muito grande no armazenamento. Mas isso tem seu ônus, principalmente no Elasticsearch, onde falo mais sobre isso no artigo.

Particionamento e Replicação dos dados

Tanto o Elasticsearch quanto o MongoDB trabalham com o conceito de Sharding, que é nada mais, nada menos que particionar seus dados entre vários servidores (nodes), utilizando os recursos compostos para melhorar a performance.

No Elasticsearch, o shard é a capacidade de subdividir o seu index em várias partes. Cada fragmento é, por si só, um “index” totalmente funcional e independente que pode ser hospedado em qualquer node do cluster. Tendo isso em mente, o sharding é importante por:

  • Permitir que você divida e escale horizontalmente seu volume do index, além de permitir distribuir e paralelizar operações entre fragmentos (potencialmente em múltiplos nodes), aumentando assim o desempenho/throughput
  • Permitir que em um ambiente de rede/nuvem, onde as falhas podem ser esperadas a qualquer momento, exista um mecanismo de failover no caso de um shard/node de alguma forma fique offline ou desapareça por qualquer motivo. Para isso, o Elasticsearch permite que você faça uma ou mais cópias dos fragmentos do seu index no que são chamados shards de réplicas.

Já os nodes (servers) podem ser de várias formas, e executam funções diferentes (que podem ser acumuladas no mesmo server, dependendo da sua arquitetura), como data-nodes, ingest-nodes, coordinator-nodes, tribe-nodes, etc. A documentação é bem completa e robusta sobre o assunto e vale uma leitura, principalmente se você for trabalhar em modelos com alta ingestão de dados e consultas.

Exemplo de distribuição de Nodes / Shards / Replicas no Elasticsearch. No exemplo, temos 3 nodes, com 3 shards e 1 réplica. Toda esta estrutura pode servir para armazenar um ou mais Índices do ES.

No MongoDB é bem parecido a estrutura, porém mais simplória e com a nomenclatura um pouco diferente. Assim como no Elasticsearch, é possível escalar de maneira vertical (aumentando a capacidade de um único servidor, como usar uma CPU mais potente, adicionar mais RAM ou aumentar a quantidade de espaço de armazenamento) e horizontal (dividindo o conjunto de dados do sistema e carregando em vários servidores, adicionando novos para aumentar a capacidade se necessário).

Os shards no Mongo, são os servers (equivalente aos nodes no Elasticsearch), tendo basicamente 3 tipos: os mongo server, shard server e config server.

Os mongos (routers) são os que recebem as consultas, e funcionam como roteadores. Eles são os responsáveis pelo direcionamento para qual shard será encaminhada a consulta, sendo a interface real entre o shard server e a aplicação. Já o shard server é onde as collections de fato estão e por fim, temos os config servers, que são onde estão armazenados os dados para mongo server gerenciar a distribuição dos dados. entre os shards.

Desenho com a demonstração de uma arquitetura simples de Sharded Cluster do MongoDB em produção.

Quanto aos dados, no MongoDB eles podem ser particionados como nos RDBMS normais, utilizando Hash e Range Partition. E são particionados em chunks através de uma Shard Key pré definida na collection. Isso aumenta bastante a capacidade do cluster em leitura/escrita, alta disponibilidade e capacidade de storage.

Não trazem em seu core os conceitos de “transação”

Enquanto no Elasticsearch não existe suporte nenhum para garantir a integridade dos dados após manipulações não atômicas dos mesmos. ou seja, caso você dê um DELETE no seu índice, ele vai embora e “simples assim”. (Não haverão constraints e nem deadlocks para te salvar. Nem ao menos uma mensagem de confirmação. Então fique esperto!), o MongoDB é quase um ACID, segundo ele mesmo, (mas não muito perto de ser igual um RDBMS).

Apesar de conseguir suportar o conceito até em nível de documento (apenas um, o que funciona na maioria dos casos), sua arquitetura focada em alta disponibilidade privilegia a mesma ao invés da forte consistência, para manter sua capacidade de escala. Ainda sim, o Mongo demonstra-se muito confiável quando configurado da maneira correta e tendo discos e memórias disponíveis.

UPDATE — 02/03/2018: O MongoDB anunciou que, para a release 4.0 que sai no próximo semestre, terá suporte a Transactions. Você pode ler o post aqui.

Open source

As duas ferramentas são open source, sendo o Elasticsearch com a licença “Apache 2.0” derivada do Apache Lucene e o MongoDB com “AGPL version 3.0, commercial license available”. Os dois vendem produtos em cima das plataformas, mas mantém seu core liberado para comunidade sob as licenças acima.

Outra coisa super importante e responsável em boa parte pelo sucesso de ambas, são suas enormes comunidades ativas, e a frequência com que soltam releases, sendo as últimas em 2018, de ambas as ferramentas.

Além disso, uma coisa que pode ser considerado um diferencial são seus ótimos manuais e documentação super bem explicada, sendo rica e, às vezes, até extensa, e fóruns ativos pela comunidade com consultores especialistas dando suporte.

As principais diferenças entre Elasticsearch e MongoDB

Database Model

Apesar de armazenar documentos em formato JSON, o Elasticsearch não é um banco de dados NoSQL em padrão Document-Store. Seu padrão é de Search Engine, ou seja, utilizado para Full-Text Search (FTS), Stemming, Buscas Geoespaciais, Logs Transacionais, Classificação e Ranking de resultados de pesquisa, sempre focando a performance em buscas em uma extensa massa de dados.

O MongoDB utiliza o padrão de "document-store", onde sua principal característica é ser schema-free para organização dos dados. Isso significa que os registros não precisam ter uma estrutura uniforme, podendo registros diferentes possuírem colunas diferentes. Além disso, as colunas podem ser diferentes uma das outras a cada registro, tendo um ou mais valores (como arrays), sendo normalmente utilizado a notação JSON para guardá-los no banco de dados.

Indexação

A indexação em quase tempo real e poder de busca do ES, vem do Lucene (utilizando o “inverted index”), que permite a criação de índice em cada campo de um documento por padrão, ou seja, performando para buscas e inserções de larga escala.

Exemplo de funcionamento do "Inverted Index" do Lucene

Apesar disso, as indexações no Elasticsearch costumam ser mais lentas que nos bancos NoSQL, mas em compensação, suas pesquisas e agregações podem ser muito mais rápidas e com grau de complexidade bem elevado.

No caso do MongoDB temos de definir o índice nas colunas desejadas, principalmente quando trabalhamos com Shard Keys. Por padrão, esses índices são, normalmente, baseados em B-Tree, (apesar de haver vários outros tipos), o que melhora o desempenho da consulta mas, afeta as operações de gravação.

Armazenamento

O Elasticsearch armazena exatamente o documento em formato em JSON num Lucene Index. Sem alteração alguma no objeto, ele o utiliza para fazer as suas agregações, classificações e scores. Sendo assim, se torna limitado ao manusear os dados antes de terem sidos indexados no índice. Contudo, é possível através do Logstash ou do próprio pipeline do ingest-node do ES, fazer as transformações necessárias antes de indexar o documento no índice. Outro ponto que vale lembrar, é que ter seus índices bem mapeados e com as tipagens corretas vão ditar boa parte d saúde das suas buscas do seu índice.

Agora, embora pareça exatamente como um documento JSON para o usuário final, o MongoDB armazena os documentos no formato BSON (Binary JSON). Outra coisa bem legal e importante é que o MongoDB suporta o gridFS. Isso lhe dá capacidade de lidar com grandes documentos (>16MB), armazenando-os de forma binária em “chunks” de arquivos, que o faz gerar vários documentos do mesmo documento, e ainda assim oferecendo a capacidade de utilizar a mesma interface de schema para retornar os dados. Além disso, a partir da versão 3.2 o MongoDB consegue guardar os documentos apenas na memória, caso utiliza-se “In-Memory” como storage engine da collection.

Lidando com o Schema

A premissa do ES sempre foi indexar e buscar por documentos através de FTS (Full-Text Search), e por esse motivo, ele não é apenas schema-free, como schemaless, e isso pode te dar uma certa dor de cabeça. Como você pode indexar quase qualquer coisa sem mapear antecipadamente seu índice (schemaless), o ES pode adivinhar o mapeamento de maneira errada e/ou não performática, selecionando um tipo para sua coluna que não é o mais adequado. Isso é um grande problema, pois, uma vez inserido o documento no índice, não é possível mais alterar os tipos das colunas do seu documento. Para alterar, é necessário o Reindex dos documentos, o que pode ser bem custoso e trabalhoso, pois terá que mapear o índice da maneira correta e os documentos podem não suportarem o mapping novo sugerido.

Quanto ao Mongo, ele vai conseguir lidar bem com quase todo tipo de conversão entre tipos dos dados, já que o dado é tratado na perspectiva do JavaScript, que é uma linguagem fracamente tipada. Embora na grande maioria dos casos das aplicações o tipo de dado de uma coluna seja parte importante e normalmente bem definido pela aplicação, ele lidará bem com as conversões, e caso necessite modificar um tipo, basta atualizar o documento com tipo correto do dados que ele funcionará normalmente.

Foreign Keys

O ES não possui nenhum mecanismo de relacionamento em nível de constraint entre seus dados. É possível modelar seus documentos na arquitetura de parent-child, que foi deprecada a partir da versão 6.0, tamanho custo e falta de propósito do mesmo dentro do que o Elasticsearch propõe como arquitetura, mas ainda sim é muito útil quando se quer fazer referência a uma série de objetos.

Ainda sim, a própria Elastic é bem enfática e não recomenda que utilize tal funcionalidade para “imitar” os bancos de dados relacionais. De qualquer forma, isso não significa que os dados serão consistentes e/ou serão persistidos. Uma vez que o documento pai é deletado, o filho persiste no shard, e pode ser encontrado através de seu ID, mas ficará órfão e não será localizado pelo ID do pai e vice-versa.

Com o MongoDB, é possível utilizar o DBRef como algo similar ao funcionamento de uma "foreign key" de um RDBMS.

Triggers

No ES, existe uma funcionalidade chamada Percolate Query, que permite você indexar uma query em cima dos documentos de um ou mais índices da sua escolha, e através da API percolator, buscar determinados registros que deem “match” com a query registrada no índice. Pode funcionar como uma trigger, mas não da maneira usual dos RDBMS. De qualquer forma, é bem útil para gravar e trazer queries predeterminadas, como num alerta de preço ou categorizar suas buscas pelo documento. A apresentação do Lucca Cavana, membro do grupo de Elasticsearch de BeLux (Bélgica e Luxemburgo), explica bem esses conceitos e onde utilizá-los de maneira prática.

Apesar dos vários hacks para incluir a funcionalidade de trigger equivalente nos banco de dados relacionais como o Tailable Cursors, e a existência de módulos como Mongo Watch, a arquitetura do MongoDB não foi feita para privilegiar triggers. Se perde muito em performance e muito da sua premissa inicial, que é de escalar/replicar o dado, mesmo que haja perda. Como a trigger é dependente de uma ação atômica para acontecer, oneraria extremamente a performance indo contra o objetivo inicial do Mongo.

User/Role Management

O Elasticsearch não foi projetado inicialmente para persistir dados de maneira segura, e sim como uma API robusta para FTS. Ao passar dos anos e versões, com os avanços da stack e utilizações diversas do seus usuários, a Elastic tendo ciência da sua fragilidade quanto a quesitos de segurança, criou o X-Pack Security, que é um pacote com várias implementações que criam tais regras de user/role management, que podem ser acessados visualmente pelo Kibana. Infelizmente, o pacote é pago e só é possível utilizá-lo pagando por uma licença. Ainda sim, não tem como foco consistência dos dados, e sim muito mais questão de auditoria dos mesmos e diminuição nas falhas de segurança de exposição da API na web.

Já o MongoDB, desde o início vem com a premissa de segurança dos dados, já que a idéia é sim guardar dados sensíveis de maneira documental apesar da possível “perda”, por não ser completamente ACID. Existe, inclusive uma série de mecanismos voltados para autenticação, autorização e encriptação dos usuários e dados. Não funciona exatamente como é nos RDBMS padrões, mas é com certeza muito mais robusto e confiável do que no Elasticsearch.

Métodos de acesso

O Elasticsearch utiliza-se de sua API Java RESTful no topo do Apache Lucene para fornecer todo acesso e gerenciamento dos documentos, índices e cluster, sendo assim de fácil conexão por utilizar como protocolo e retorno HTTP/JSON, o que a torna também mais vulnerável nos quesitos de segurança.

Já o MongoDB utiliza-se de protocolo próprio, baseado em socket de request-response, utilizando na comunicação com o client os protocolos TCP/IP, implementando camadas de seguranças necessárias para se manter mais robusto.

Queries

Neste quesito os dois tem suas linguagens próprias para query, não sendo SQL-Like. Enquanto o Elasticsearch possui uma API _search acessada via REST, que combinada com as “Query DSL”, que utilizam JSON como base, o MongoDB tem uma linguagem própria, bem parecida com Javascript para fazer as suas queries, que é bem explicada, sendo feita até comparação com o padrão SQL no próprio manual do Mongo. Apesar disto, é possível utilizar SQL no MongoDB, através do seu conector para BI, mas que é pago e só funciona para licenças enterprise.

Mas e aí? Quem é o melhor?

Aparentemente, os dois se parecem, mas só aparentemente. Apesar de conseguirem armazenar objetos de “chave-valor” em JSON e serem possíveis de se fazer query em seus documentos, temos que ter em mente que cada um veio para cumprir uma proposta: enquanto o MongoDB vem com a proposta de ser um banco de dados com um propósito um pouco mais genérico, tendo como grande trunfo sua escalabilidade horizontal e vertical e ser schema-free, o Elasticsearch é excepcional para indexação, tendo como grande trunfo para tal objetivo, a utilização do “inverted-index” do Apache Lucene. Portanto é extremamente recomendável para pesquisas e agregações de grandes datasets, sendo altamente estável, escalável e robusto, além de ter um futuro promissor na área de analytics e machine learning com suas últimas releases. Mas, nada além disso.

Como o Cloud Tech Lead da Elastic Alex Brasetvik diz neste excelente artigo, "Elasticsearch as a NoSQL Database":

"It is certainly possible to use Elasticsearch as a primary store, when the limitations described are not showstoppers." — BRASETVIK, Alex

Caso seja necessário ter as duas coisas em uma (um banco robusto nos sentidos de segurança, ACID, com a necessidade de pesquisa em texto e ao mesmo tempo relações entre objetos armazenados em JSON), recomendo utilizar o PostgreSQL como seu banco "object-relational", já que tem uma ótima cobertura para Full-Text Search e a robustez necessária de um banco relacional altamente testado, com uma maturidade e comunidade incrível, já que é um projeto de código aberto com mais de 20 anos de existência.

Quanto a relação entre Elasticsearch e MongoDB, o ideal é que os dois trabalhem juntos (como fazemos na MaxMilhas), deixando para o MongoDB o trabalho duro de manter as restrições de usuários, a robustez e consistência, a sua facilidade e praticidade de integração com o desenvolvedor (por utilizar JavaScript e a notação JSON para armazenamento de dados semi-estruturados), e que o Elasticsearch seja uma camada de apresentação de dados não-sensíveis, preferencialmente não mutáveis e bem mapeados, para que possam ser agregados de diversas formas com a rapidez necessária.

Gostou do texto? Tem alguma dúvida, crítica e/ou sugestão? Use os comentários para me mandar feedbacks e compartilhe com quem interessar sobre o assunto! :D

Ah! Antes que eu me esqueça, não deixem de se inscrever no Data Hackers: a primeira Comunidade Brasileira de Data Science e Big Data, e receba os melhores conteúdos, dicas e ajuda de profissionais da área. Tudo isso de graça!

Abraços e até mais! ❤

--

--

Vinícius Coimbra
Data Hackers

Technology and Innovation Executive | Data | Product | Digital Transformation | Software Engineering | Advisor | Mentor | Songwriter @ProjetoRiviera