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.

    Exportando para um arquivo
    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.
    Impressões e Conclusão
    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.
    Referências

    27

    This website collects cookies to deliver better user experience

    Exportando dados filtrados em mais de uma collection