16
Exportando dados filtrados em mais de uma collection
Imagine a seguinte situação:
A equipe estratégica da montadora deseja criar um relatório contendo todas as vendas feitas no mês de agosto de 2020 tanto pela concessionária quanto direto pela fábrica.
O sistema da montadora divide essas vendas em duas collections do mongo.
O relatório é gerado por uma ferramenta consolidada de mercado que aceita a importação dos dados por arquivos .csv ou .json
A primeira solução que vem à cabeça é utilizar o mongoexport com o parâmetro --query para gerar os dados solicitados. No entanto, o mongoexport possui a limitação de só exportar dados de uma única collection por vez.
Fazendo um teste simples de exportar todos os dados de um database sem definir uma collection com o mongoexport obtemos o seguinte resultado:
#$> mongoexport mongodb://localhost:27017 --db examples #comando executado
2021-08-26T08:39:03.607-0300 must specify a collection
2021-08-26T08:39:03.615-0300 try 'mongoexport --help' for more information
Usando o mongosh
O mongosh é a ferramenta básica para interagir com qualquer mongodb. Utilizando ele é possível criar consultas, procedures, indexes e gerenciar o database de maneira geral. Outro ponto interessante é que possível importar scripts .js e executá-los dentro do mongosh. É possível importar o arquivo de duas formas:
- Importar diretamente dentro do mongosh
mongosh mongodb://localhost:27017
> load('export_data_multiple_databases/obter_vendas.js')
- Importar no momento da execução do mongosh
mongosh mongodb://localhost:27017/examples ~/export_data_multiple_databases/obter_vendas.js
No primeiro caso os resultados gerados são mostrados diretamente no console do mongosh (contexto do mongosh), tornando a tarefa exportar os dados complexa para o cenário apresentado.
Exemplo de execução
Current Mongosh Log ID: 612918a2e3f888785924e0e9
Connecting to: mongodb://localhost:27017/examples?directConnection=true&serverSelectionTimeoutMS=2000
Using MongoDB: 5.0.0
Using Mongosh Beta: 0.14.0
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
------
The server generated these startup warnings when booting:
2021-08-27T10:16:56.220+00:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
2021-08-27T10:16:56.525+00:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
2021-08-27T10:16:56.526+00:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
------
> load('~/export_data_multiple_databases/obter_vendas.js')
[{
fabricante: 'Lexus',
modelo: 'LS',
ano: 2004,
datavenda: ISODate("2021-08-03T00:00:00.000Z"),
preco: '$106375.36',
collectionName: 'vendas_concessionaria'
},
{
fabricante: 'GMC',
...
Já no segundo caso é possível exportar diretamente para um arquivo externo, pois o comando devolve o resultado no contexto do console e não no contexto do mongosh.
Importante ressaltar que o script importado fica disponível somente naquela sessão.
A forma mais simples de exportar para um arquivo é justamente usando o segundo comando de importação de scripts.
mongosh mongodb://localhost:27017/examples ~/export_data_multiple_databases/obter_vendas.js > arquivo_resultado.json
Mongosh --eval
O parâmetro --eval executa um script js inline usando o contexto do mongosh, porém sem carregar o ambiente do mongosh no console. O resultado é da execução é enviado para o console conforme exemplo abaixo:
mongosh mongodb://localhost:27017/examples --eval="load('export_data_multiple_databases/obter_massa_dados.js');"
Como resultado é enviado diretamente para o console (fora do contexto do mongosh), exportar os dados para um arquivo .json é simples
mongosh mongodb://localhost:27017/examples --eval="load('export_data_multiple_databases/obter_massa_dados.js');" > arquivo_resultado.json
A vantagem em relação à exportação padrão é que com o --eval é possível adicionar outras instruções além do que está no script.
Eliminando o cabeçalho com o parâmetro --quiet
Examinando o arquivo exportado, nota-se que os cabeçalhos de inicialização do mongosh também foram exportados.
Current Mongosh Log ID: 6129153e30afffaa9fb76fe4
Connecting to: mongodb://localhost:27017/examples?directConnection=true&serverSelectionTimeoutMS=2000
Using MongoDB: 5.0.0
Using Mongosh Beta: 0.14.0
For mongosh info see: [1mhttps://docs.mongodb.com/mongodb-shell/]
-----------
The server generated these startup warnings when booting:
2021-08-27T10:16:56.220+00:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
2021-08-27T10:16:56.525+00:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
2021-08-27T10:16:56.526+00:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
-----------
Loading file: ~\export_data_multiple_databases\obter_vendas.js
[{
fabricante: 'Hyundai',
modelo: 'Genesis',
ano: 2009,
...
Para resolver este problema basta adicionar o parâmetro --quiet ao comando de exportação.
Através do método de importação pela linha de comando:
mongosh mongodb://localhost:27017/examples --quiet ~/export_data_multiple_databases/obter_massa_dados.js > arquivo_resultado.json
Usando o --eval:
mongosh mongodb://localhost:27017/examples --quiet --eval="load('export_data_multiple_databases/obter_massa_dados.js');" > arquivo_resultado.json
Ao examinar novamente o arquivo, nota-se que o cabeçalho sumiu e com isso temos um arquivo .json válido e somente com os dados solicitados.
A ideia deste post surgiu de uma tarefa que solicitava a exportação de dados oriundos de um schema específico para csv. Tal schema existia em diversas collections com documentos que possuiam campos diferentes entre si. O único ponto em comum dessas collections era justamente um subdocumento com o schema em questão.
Como não sou um profundo conhecedor de mongodb e não encontrei uma forma fácil na documentação e muito menos no stackoverflow e afins, resolvi ser criativo. Me vali da capacidade do mongodb de executar scripts .js e de conhecimentos básicos de shell.
A solução é um tanto verbosa, porém resolveu meu problema de forma simples e eficiente. Imagino que os especialistas em mongodb vão me contar nos comentários:
- basta rodar essa linha de comando que você obtém o mesmo resultado
Mas até lá, vou seguir usando a mesma abordagem para obter esses dados sempre que forem solicitados.
No github (pasta export_data_multiple_databases) deixei o passo a passo de como reproduzir esse post.
Quero deixar um agradecimento especial para o Caio Lucena pelas revisões dos posts publicados até agora.
16