NoSQL Relacional com MongoDB

Thiago Cerqueira
Agile Content Teamwork
5 min readJul 10, 2018

Eu tive uma conversa com uma colega, DBA de SQL Server. Ela tinha me dito que não sabia quase nada sobre “NoSQL” mas acreditava que “é o futuro!”. Aqui vou dizer que, se você conhece bancos de dados relacionais, você já conhece o básico de MongoDB, um dos bancos de dados NoSQL mais usados por aí. Talvez você já esteja pronto pro futuro!

O misterioso mundo do NoSQL

Então, o que é NoSQL?

Eu sei! Eu sei! É um monte de JSON!

Bem… não. Que dizer, não muito. A diferença é mais na forma em que você acessa os dados do que como eles são armazenados.

Tem um monte de db’s NoSQL por aí com diferentes estruturas que são usadas para problemas específicos. Como grafos para redes de conexões, pessoas, cidades; ou arrays associativos (ou KV, key-value) usados para cache. E existem dbs orientados a documentos que usam sintaxes como XML ou JSON para manipular os dados, MongoDB é um deles.

O que todos eles têm em comum é que eles tendem a evitar a “Linguagem de Consulta Estruturada” para retornar dados. Not only SQL, como dizem por aí.

Mas é muito diferente de SQL?

Às vezes. A preferência por outras sintaxes se dá porque elas funcionam melhor para algumas estruturas de dados ou casos de uso.* Se você tem uma estrutura KV, por exemplo, você só precisa da chave pra procurar o valor.

Não é o caso do MongoDB.

* Existem algumas diferenças em como distribuir os dados, partição de rede e outras coisas como o Teorema CAP. Mas não quero falar sobre isso hoje.

Mesmos conceitos, estrutura diferente

Imagine que nós temos uma aplicação de vídeo sob demanda (VOD para os íntimos) só de filmes de super-heróis. Hoje você vai lá e cria um banco de dados relacional com uma tabela Filmes para o nosso catálogo, algo como esta aqui:

+--+-----------------+-------+---------------+-----------+
|id|title |year |publish_date |studio_fk |
+--+-----------------+-------+---------------+-----------+
|1 |"Justice League" |2017 |2018-02-10 |1 |
|2 |"Deadpool" |2016 |2017-10-19 |3 |
|3 |"Wonder Woman" |2017 |2017-09-19 |1 |
|4 |"Captain America"|2016 |2017-09-19 |2 |
+--+-----------------+-------+---------------+-----------+

Junto com uma tabela de Estúdios. Índices, foreign keys, normalização e essas coisas. Sabe como é. Não vamos pensar sobre isso agora.

Eu já falei que MongoDB usa uma sintaxe parecida com JSON para guardar dados, não tabelas. Então como, por exemplo, seria o registro “Deadpool”?

{
"_id": 2,
"title": "Deadpool",
"year": 2016,
"publish_date": Date("2017-10-19"),
"studio": {
"name": "21th Century Fox",
"logo": "url_to_fox_logo.png"
}
}

Nossa! Nem é tão diferente assim!

Dá pra ver o padrão, né!? Tem algumas coisas estranhas, mas a maioria dos nomes das colunas foram traduzidos para campos do JSON e os valores atribuídos respectivamente.

Outra coisa em comum nesse caso é que o _id age como uma chave primária: tem que existir e seu valor tem que ser único. Se você não passar um quando inserir um registro, o banco de dados gera um pra você.

Então existe uma chave primária. Quer dizer que tem índice também?

Sim, tem sim. Os indices são definidos para cada coleção de documentos chamados…bem… collections! E collections se comportam de maneira parecida com tabelas. A única diferença real é que vocẽ não precisa especificar o esquema dos dados. Se o índice não consegue encontrar a chave, ele trata isso como null ou impede você de inserir o documento, dependendo de como você criou o índice. Bem parecido com o SQL Server.

Legal! E aquele studio que tem no final?

Ah é! Quase esqueci! Se você precisar desnormalizar seus dados, por questão de performance (ou mesmo sanidade), você pode incluir outro documento dentro dele mesmo, e até realizar consultas nele.

Por falar em query

Como você pede os dados nesse banco? Vou começar com a sintaxe SQL de novo.

Se você precisa listar os filmes do estúdio “Warner”, em ordem reversa de publicação, você escreveria algo assim:

SELECT title, publish_date
FROM dbo.Movies AS movie
JOIN dbo.Studios AS studio ON movie.studio_fk = studios.id
WHERE studio.name='Warner'
ORDER BY publish_date DESC

Vamos traduzir para a linguagem que o MongoDB entende, que por acaso é JavaScript.

var filter = {"studio.name": "Warner"};
var projection = {"title": 1, "publish_date": 1, "_id": 0};
var order = {"publish_date": -1};
db.movies.find(filter, projection).sortBy(order);

Perceba a semelhança! O db.movies ali no final significa que estamos na collection movies no banco atual, igual a cláusula FROM. O filter funciona como o WHERE, com uma ajudinha da desnormalização aqui. A cláusula SELECT é convertida em um objeto JSON chamado projection. E o ORDER BY vai dentro do método sortBy, com -1 indicando ordem decrescente.

A grande diferença nesse exemplo é que você precisa explicitamente dizer que o campo _id não deve ser retornado escrevendo "_id": 0 no projection, já que o padrão é que ele sempre é retornado.

Igual mas diferente

Os dois sistemas de banco de dados são bem parecidos, mas qual a diferença no MongoDB afinal? Além da estrutura de dados e a linguagem de consulta, tem algumas coisas que os desenvolvedores do MongoDB decidiram deixar de lado. A maioria porque, na visão deles, essas características poderiam tornar difícil trabalhar com dados distribuídos do jeito que eles queriam.

A maior delas é a ausência de Transações.

É por isso que muitos desenvolvedores e dba’s usam documentos aninhados quando projetam um banco de dados MongoDB. Claro, quando você aninha documento, existe um limite no tamanho documento, e algumas vezes pode causar alguns updates estúpidamente complexos e lentos. Eu recomendo usar isso com cuidado. Existe um ótimo tutorial de como criar operações transacionais em documentos MongoDB, então você pode “normalizar” seus dados através de collections e tratar alguns updates complexos em mais de um documento.

Resumindo

Vamos ver o que aprendemos:

  • Os documentos JSON em MongoDB são basicamente entradas SQL com {}
  • Collections são tipo tabelas
  • _id é uma chave primária obrigatória
  • Quando consultamos o MongoDB nós usamos todos os elementos de uma consulta SQL, mas escrito em JavaScript.
  • Não tem Transações

Esse é o básico. Espero que você se sinta mais confortável para pesquisar sobre bancos de dados NoSQL após ver que não é tão diferente assim. Talvez isso ajude a melhorar suas habilidades e a forma de pensar no SQL. Quem sabe?

Usei o MongoDB como exemplo por causa dessas semelhanças. Se você quiser saber sobre mais bancos de dados, com outros paradigmas, recomendo o livro Seven Databases in Seven Weeks.

É isso aí. Que a Força esteja com vocês.

Originalmente publicado em thiagoabreu.github.io (in english)

--

--