MongoDB Aggregation

Fazer buscas mais complexas e unir vários documentos, com o Aggregation Framework.

[ Hits: 8.210 ]

Por: Alisson Machado em 24/10/2017


Introdução



Em minha jornada infinita de aprender coisas novas em T.I., nos assuntos DevOps, BigData, DataScience, Clusters, Virtualização e tudo mais.

Estou essa semana focado em extrair relatórios do MongoDB para fazer learning analytics pro Moodle, como o MongoDB é um banco de dados noSQL, não existe o relacionamento entre tabelas, como somos acostumados em bancos de dados SQL.

Sendo assim, para fazer buscas mais complexas e unir vários documentos, pode-se usar o Aggregation Framework.

Aggregation é uma forma de processar documentos distintos com o objetivo de agrupar em uma única saída, facilitando assim a geração de resultados e performance na hora de efetuar essas buscas.

Abaixo, vou explicar vários parâmetros sobre como utilizar esse recurso e elaborar buscas mais específicas.

ATENÇÃO: todos os comandos abaixo foram executados na versão 3.4 do MongoDB.

mongo
MongoDB shell version: 3.2.11
connecting to: test
use exemplo
switched to db exemplo


No log acima, entrei no console do MongoDB e acessei o banco exemplo, nesse banco vou criar uma collection chamada "funcionários" e inserir alguns registros:

db.funcionarios.insert({"nome":"Alisson","sobrenome":"Machado de Menezes","cargo":"Analista de Sistemas DevOps", "empresa":"4Linux"})
WriteResult({ "nInserted" : 1 })

db.funcionarios.insert({"nome":"Mariana","sobrenome":"Albano","cargo":"Analista de Sistemas DevOps", "empresa":"4Linux"})
WriteResult({ "nInserted" : 1 })

db.funcionarios.insert({"nome":"Antonio","sobrenome":"Gomes","cargo":"Supervidor de Suporte", "empresa":"4Linux"})
WriteResult({ "nInserted" : 1 })

db.funcionarios.insert({"nome":"Gabriel","sobrenome":"Bonfim","cargo":"Desenvolvedor Senior", "empresa":"4Linux"})
WriteResult({ "nInserted" : 1 })

db.funcionarios.insert({"nome":"Hederson","sobrenome":"Boechat","cargo":"Desenvolvedor Senior", "empresa":"Nadir"})
WriteResult({ "nInserted" : 1 })

db.funcionarios.insert({"nome":"Guilherme","sobrenome":"Chagas","cargo":"Analista de Sistemas DevOps", "empresa":"BankFacil"})
WriteResult({ "nInserted" : 1 })

db.funcionarios.insert({"nome":"Hederson","sobrenome":"Boechat","cargo":"Desenvolvedor Senior", "empresa":"Nadir"})
WriteResult({ "nInserted" : 1 })

db.funcionarios.insert({"nome":"Fernando","sobrenome":"Paiva","cargo":"Analista de B.I", "empresa":"Lemman"})
WriteResult({ "nInserted" : 1 })

Para listar todos os documentos, digite a instrução abaixo:

db.funcionarios.find()
{ "_id" : ObjectId("58a7479844f122d1903c551f"), "nome" : "Alisson", "sobrenome" : "Machado de Menezes", "cargo" : "Analista de Sistemas DevOps", "empresa" : "4Linux" }
{ "_id" : ObjectId("58a747a144f122d1903c5520"), "nome" : "Mariana", "sobrenome" : "Albano", "cargo" : "Analista de Sistemas DevOps", "empresa" : "4Linux" }
{ "_id" : ObjectId("58a747ac44f122d1903c5521"), "nome" : "Antonio", "sobrenome" : "Gomes", "cargo" : "Supervidor de Suporte", "empresa" : "4Linux" }
{ "_id" : ObjectId("58a747b644f122d1903c5522"), "nome" : "Gabriel", "sobrenome" : "Bonfim", "cargo" : "Desenvolvedor Senior", "empresa" : "4Linux" }
{ "_id" : ObjectId("58a747c044f122d1903c5523"), "nome" : "Hederson", "sobrenome" : "Boechat", "cargo" : "Desenvolvedor Senior", "empresa" : "Nadir" }
{ "_id" : ObjectId("58a747c844f122d1903c5524"), "nome" : "Guilherme", "sobrenome" : "Chagas", "cargo" : "Analista de Sistemas DevOps", "empresa" : "BankFacil" }
{ "_id" : ObjectId("58a747d144f122d1903c5525"), "nome" : "Hederson", "sobrenome" : "Boechat", "cargo" : "Desenvolvedor Senior", "empresa" : "Nadir" }
{ "_id" : ObjectId("58a747da44f122d1903c5526"), "nome" : "Fernando", "sobrenome" : "Paiva", "cargo" : "Analista de B.I", "empresa" : "Lemman" }


Agora que a base dados já está populada, é possível utilizar do Aggregate para filtrar essas buscas. Por exemplo, se eu quiser buscar todos os funcionários que trabalham na empresa 4linux:

db.funcionarios.aggregate([{"$match":{"empresa":"4Linux"}}])
{ "_id" : ObjectId("58a7479844f122d1903c551f"), "nome" : "Alisson", "sobrenome" : "Machado de Menezes", "cargo" : "Analista de Sistemas DevOps", "empresa" : "4Linux" }
{ "_id" : ObjectId("58a747a144f122d1903c5520"), "nome" : "Mariana", "sobrenome" : "Albano", "cargo" : "Analista de Sistemas DevOps", "empresa" : "4Linux" }
{ "_id" : ObjectId("58a747ac44f122d1903c5521"), "nome" : "Antonio", "sobrenome" : "Gomes", "cargo" : "Supervidor de Suporte", "empresa" : "4Linux" }
{ "_id" : ObjectId("58a747b644f122d1903c5522"), "nome" : "Gabriel", "sobrenome" : "Bonfim", "cargo" : "Desenvolvedor Senior", "empresa" : "4Linux" }


Caso queira agrupar os valores, é possível utilizando a instrução $group. Essa instrução, obrigatoriamente, precisa que seja passado um _id e esse aí deve ser um campo do documento retornado.

Por exemplo:

$ db.funcionarios.aggregate([{"$match":{"empresa":"4Linux"}},{"$group":{"_id":"$nome"}}])
{ "_id" : "Gabriel" }
{ "_id" : "Mariana" }
{ "_id" : "Antonio" }
{ "_id" : "Alisson" }


Para ver o total de documentos agrupados, pode-se utilizar a instrução $sum:

db.funcionarios.aggregate([{"$match":{"empresa":"4Linux"}},{"$group":{"_id":"$empresa","total":{"$sum":1}}}])
{ "_id" : "4Linux", "total" : 4 }

Para contar todos os resultados sem o agrupamento, pode-se utilizar a instrução $count, essa instrução só existe a partir da versão 3.4:

db.funcionarios.aggregate([{"$match":{"empresa":"4Linux"}},{"$count":"total"}])

É possível também projetar uma saída, ou seja, modelar o documento e mostrar apenas campos específicos aumentando a performance da sua busca e trazendo resultados mais fáceis de se encontrar. Por exemplo:

db.funcionarios.aggregate([{"$match":{"empresa":"4Linux"}},{"$project":{"nome":1,"cargo":1}}])
{ "_id" : ObjectId("58a7479844f122d1903c551f"), "nome" : "Alisson", "cargo" : "Analista de Sistemas DevOps" }
{ "_id" : ObjectId("58a747a144f122d1903c5520"), "nome" : "Mariana", "cargo" : "Analista de Sistemas DevOps" }
{ "_id" : ObjectId("58a747ac44f122d1903c5521"), "nome" : "Antonio", "cargo" : "Supervidor de Suporte" }
{ "_id" : ObjectId("58a747b644f122d1903c5522"), "nome" : "Gabriel", "cargo" : "Desenvolvedor Senior" }


No exemplo acima, pode-se ver que foi foram mostrados somente os campos _id, nome e cargo, sendo assim, quando se quer mostrar um campo, coloca-se o valor 1 em conjunto com a chave; caso não queira, pode-se colocar o valor 0.

Por exemplo:

db.funcionarios.aggregate([{"$match":{"empresa":"4Linux"}},{"$project":{"nome":1,"cargo":1,"_id":0}}])
{ "nome" : "Alisson", "cargo" : "Analista de Sistemas DevOps" }
{ "nome" : "Mariana", "cargo" : "Analista de Sistemas DevOps" }
{ "nome" : "Antonio", "cargo" : "Supervidor de Suporte" }
{ "nome" : "Gabriel", "cargo" : "Desenvolvedor Senior" }


No exemplo acima foi ocultado o campo _id, para melhorar a visualização do documento.

O Aggregation do MongoDB trabalha com um esquema de pipeline, ou seja, você pode concatenar todas as instruções juntas.

Por exemplo: pode-se fazer um $match, depois um $project para limitar os campos e depois um $group, para agrupar pelos cargo e saber quantas pessoas daquela posição existem na empresa.

db.funcionarios.aggregate([{"$match":{"empresa":"4Linux"}},{"$project":{"nome":1,"cargo":1,"_id":0}},{"$group":{"_id":"$cargo","total":{"$sum":1}}}])
{ "_id" : "Desenvolvedor Senior", "total" : 1 }
{ "_id" : "Supervidor de Suporte", "total" : 1 }
{ "_id" : "Analista de Sistemas DevOps", "total" : 2 }


Esses são os comandos básicos para fazer um Aggregate no MongoDB.

Qualquer dúvida, é só me dar um salve.
Alisson Machado - http://alissonmachado.com.br

   

Páginas do artigo
   1. Introdução
Outros artigos deste autor

Vault: SSH com OneTimePassword

Python Flask Básico

Sincronizando Dados do PostgreSQL no Elasticsearch

Python + ADB

paramiko - Python + SSH

Leitura recomendada

Gerencie suas informações através de instruções SQL com selects turbinados (para leigos e experts)

Implementação LDAP e Java

Informix: Instalação - Configuração - Conceito

Instalando o poderoso banco de dados IBM DB2!

Como criar VIEWS no MySQL

  
Comentários
[1] Comentário enviado por iksme em 13/11/2017 - 17:43h

Parabéns pelo artigo, não vou poder testar porquê decidir usar mongo hoje em um projeto mas tenho certeza que vou essa técnica de aggregation.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts