MongoDb - Como mudar seu jeito relacional de pensar - Parte 1

Muitos me perguntam como devem modelar uma base com MongoDb ou como deixar de pensar relacional. Bom eu já uso o MongoDb há 4 anos então já estou acostumado com seu modelo de dados, mas posso dar algumas dicas para você reconhecer alguns padrões e conseguir modelar melhor sua base não relacional.

Vamos iniciar com um dos modelos mais simples e exemplificados, o blog:

imagem retirada do livro MongoDb in Action

Já no MongoDB nós transformarmos ele nessa coleção:

Vamos analisar como podemos fazer essa transformação.

N:N

Um padrão que eu percebi na minha experiência é que boa parte das tabelas que são do tipo N:N podem ser traduzida para o MongoDb na forma de um array com os valores agregados diretamente no documento "pai", mas hein?

Bom vamos ao exemplo ali das TAGS, como você pode perceber a tabela tag é ligada na tabela posts_tags para ser ligada na tabela posts assim ligando qualquer tag em qualquer post, ou seja, seu post pode ter várias tags e uma tag pode ser usada em vários posts, assim você evita a duplicidade por exemplo de ter a mesma tag javascript criada 2x para ser usada em 2 posts diferentes, normalizando a base para evitar duplicidade dos dados como manda o Relacional.

Porém com JSON nosso Schema pode ser muito mais rico no MongoDB e como ele não possui JOINS quanto mais tabelas mais consultas adicionais você precisará fazer para ter todos os dados de um sistema, então como vamos traduzir esse relacionamento N:N no MongoDb?

Arrays.

Vamos ao exemplo das imagens, podemos ver o seguinte código no JSON:

tags: ['databases', 'mongodb', 'indexing'],

Enquanto que no relacional nós precisamos de 3 tabelas para agregar toda essa informação no MongoDB nós podemos adicionar diretamente no objeto que é "dono" dessa informação.

Ai você me pergunta mas Suissinha não vai duplicar os dados?

CLARO QUE VAI!

Mas o MongoDb te incentiva a isso já que não possui JOINS quanto mais informação da entidade você receber em uam só consulta melhor.

Caso você fosse fazer um sistema parecido com o Delicious que re-usa as tags ai nesse caso você faria um array de tags com os ObjectIds de cada TAG que teria seu objeto armazenado na coleção tags ai no caso você teria que fazer uma consulta no POST para pegar essa lista e buscar os registros na coleção tags. No Mongoose nós podemos utilizar o POPULATE para nos automatizar essa consulta, porém sem usar o DB Ref pois acho que não vale a pena ainda mais referenciando uma coleção que só tende a crescer, expliquei sobre o porquê não usar DBRef.

Integridade referencial

NÃO EXISTE

Mas podemos contornar isso fazendo o seguinte, caso você precise mudar a TAG mongodb em todos os registros como devemos fazer?

Primeiramente criamos nosso objeto de busca:

var query = {tags: 'mongodb'}  

Depois criamos o objeto que irá modificar o nossa tag mongodb:

var mod = {$set: { 'tags.$': 'teste'}}  

Aí rodamos nossa query no console:

db.posts.update(query, mod, false, true)  

Na função do update passamos no primeiro parâmetro a busca de quais elementos queremos alterar, no segundo parâmetro passamos o objeto que irá modificar nosso array.
No terceiro parâmetro passamos false para upsert e true para o multi

Perceba que usamos o operador $set que vai modificar o valor do campo tags utilizando o $ que é o operador posicional, ou seja, ele vai pegar o primeiro elemento que ele encontrar que seja igual a nossa query, achando o elemento correto ele irá dar o update naquele lugar no array, caso você tenha mais de um elemento com o mesmo valor a ser alterado o UPDATE só irá alterar o primeiro encontrado, o que no caso das tags está ótimo.

The positional $ operator identifies an element in an array field to update without explicitly specifying the position of the element in the array. To project, or return, an array element from a read operation, see the $ projection operator.

When used with the update() method,

  • the positional $ operator acts as a placeholder for the first element that matches the query document, and
  • the array field must appear as part of the query document.

Você também pode resolver o problema de tags duplicadas no array utilizando $addToSet

ps: Depois atualizo com uns exemplos de query de SQL e MongoDB, não agora pq estou no bar e adicionei esse PS aqui só para me lembrar LOL

Aguardem a parte 2 que mostrarei uma modelagem de um ecommerce!

Comentários

comments powered by Disqus