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

Nesse post abordarei uma modelagem um pouco mais complexa que de um sistema de blogs, será a de um catálogo de produtos, uma ideia inicial para a criação de um ecommerce.

Nosso sistema precisa ter a capacidade de armazenar vários tipos diferentes de objetos e seu relecaionamentos, isso pode implicar em vários problemas na modelagem quando se está pensando no modelo relacional ainda.

Nessa modelagem temos o produto que possui categoria e tags, o pedido que é ligado a produtos e usuários. E nosso usuário possui endereço com cidade, estado e país.

Bom você percebeu como conseguimos separar em 3 contextos diferentes nosso sistema?

  • produto
  • pedido
  • usuário

Partindo dessa informação podemos iniciar a modelagem da agregação no MongoDb, utilizando exatamente esses 3 contextos como objetos agregadores dos dados, não entendi porra nenhuma!

Ok, então vamos ao código que ficará mais fácil.

Produto

Nesse agregado juntamos as informações do produto com categoria e tags.

Pedido

No agregado do pedido ligamos os produtos e o usuário.

Usuário

Para o usuário nós agregamos o endereço, cidade, estado e país.

Conclusão

Percebeu como em vez de separarmos os dados agora nós os agregamos? É dessa forma que temos que trabalhar com o MongoDb, isso contribui muito para nossas buscas já que o MongoDb não possui JOINS e o forte dele é sua velocidade na busca, quanto mais dados agregados serem entregues em uma única query mais performático seu sistema será.

Bah mas então se que quiser buscar os pedidos eu ainda terei que ter uma query para buscar o usuário e outra para os produtos?

Exatamente!

Mas calma essa modelagem ainda não está ótima, vamos refatorar ela levando em mente que a função principal do nosso sistema de gerenciamento é a listagem dos pedidos feitos pelo usuário, nesse caso vamos agregar o pedido na coleção de usuário ficando assim:

Mas por que isso tio Suissa?

Para que nossa busca principal, que é a listagem dos pedidos do usuário, seja feita da maneira mais rápida possível apenas com duas consultas: usuário e produtos. Pois a listagem dos pedidos já está agregada no usuário não necessitando fazer uma consulta apenas para isso.

API

Usuário

Inserindo usuário

Produtos

Inserindo produto

Adicionando Produto ao Pedido

API Route Controller

Para inserir um produto nós na verdade precisamos alterar nosso usuário e atualizar o array de pedidos adicionando o objeto do nosso produto, por isso usamoso seguinte objeto modificador $push com a função de update:

var mod = {$push: {"orders.products": product}};

Model.update(query, mod, function(err, data) {
  cb(err, data, res);
});

Listando produtos por Categoria

Para listarmos os produtos através de uma categoria é bem simples no MongoDB, basta passarmos o vamos da categoria na query como abaixo (no console):

var query = {category: /frontend/i};
db.products.find(query);

Estou usando regex /frontend/i para fazer uma busca case insensitive para não termos problema se a String foi escrita com maiúsculo ou minúsculo.

Listando produtos por Tag

A busca pela Tag é um pouco diferente pois ela é um array nesse caso usaremos o operador $in para fazer a busca dentro do array por isso precisamos passar o valor dentro de um array:

var tag = req.params.tag;
var query = {tags: {$in: [new RegExp(tag, 'gi')]} };

Model.find(query, function (err, data) {
  cb(err, data, res);
});

Decrementado a quantidade total do produto

Bom obviamente precisamos decrementar o valor da quantidade dos produtos adicionados no pedido para que tenhamos um campo calculado atualizado. Para isso vamos precisar serializar duas ações no MongoDb já que todos os métodos são assíncronos podemos tanto utilizar Promisses como Async, nessa solução iremos utilizar o Async.

Pedidos

Listando pedidos

Para lista os pedidos utilizaremos o populate do Mongoose

Middlewares de rotas para PAI

Rota para listar

Função de listagem dos pedidos

Show me the code

Códido de exemplo: https://github.com/suissa/poc-order-system

ps: Esse artigo será atualizado até demonstrar todas as funcionalidades básicas que uma API precisa ter para trabalhar com um sistema simples de pedidos.

ps2: Ainda farei o comparativo usando SQLs

ps3: coloquem as queries que vcs tem dúvida em como fazer postem nos comentários abaixo

Comentários

comments powered by Disqus