Existe uma maneira de 'bem' imprimir a saída do shell do MongoDB em um arquivo?

101

Especificamente, desejo imprimir os resultados de um mongodb find()em um arquivo. O objeto JSON é muito grande, então não consigo visualizar o objeto inteiro com o tamanho da janela do shell.

víbora
fonte

Respostas:

216

O shell oferece alguns recursos interessantes, mas ocultos, porque é um ambiente interativo.

Quando você executa comandos de um arquivo javascript por meio do mongo commands.js, você não obterá um comportamento totalmente idêntico.

Existem duas maneiras de contornar isso.

(1) falsificar o shell e fazê-lo pensar que você está no modo interativo

$ mongo dbname << EOF > output.json
db.collection.find().pretty()
EOF

ou
(2) usar Javascript para traduzir o resultado de um find()em um JSON imprimível

mongo dbname command.js > output.json

onde command.js contém isto (ou seu equivalente):

printjson( db.collection.find().toArray() )

Isso imprimirá bastante o array de resultados, incluindo [ ]- se você não quiser, pode iterar sobre o array e printjson()cada elemento.

A propósito, se você estiver executando apenas uma única instrução Javascript, não precisa colocá-la em um arquivo e, em vez disso, pode usar:

$ mongo --quiet dbname --eval 'printjson(db.collection.find().toArray())' > output.json
Asya Kamsky
fonte
command.js deve ser um arquivo legível que exista em seu diretório atual e que tenha o javascript que você deseja executar.
Asya Kamsky
Como faço para um db mongo remoto? Eu tentei, mongo blah.mongolab.com:33478/blah -u user -p pass --eval "my query" >> dump.txtmas me deu JavaScript execution failed: SyntaxError: Unexpected token ILLEGAL.
Sheharyar
esse erro significa que o que está dentro de suas aspas após --eval não é uma sintaxe legal. Eu recomendo usar aspas simples fora de expressões inteiras e se você precisar de aspas dentro delas, use aspas duplas para isso.
Asya Kamsky
2
A opção 2 é realmente a única opção se você tiver mais do que um punhado de resultados, já que na opção 1 ela apenas parará em 'Digite "isso" para mais'.
Tomty
2
não exatamente @Tomty - o tamanho do lote do shell é controlável com uma variável dentro do shell. você pode colocar DBQuery.shellBatchSize = 10000 em seu arquivo .mongodbrc.js e ele irá "parar" após 10000 resultados em vez de 20.
Asya Kamsky
29

Como você está fazendo isso em um terminal e deseja apenas inspecionar um registro de maneira sã, você pode usar um truque como este:

mongo | tee somefile

Use a sessão normalmente - db.collection.find().pretty()ou o que quer que você precise fazer, ignore a saída longa e saia. Uma transcrição de sua sessão estará no arquivo em que você teeescreveu.

Esteja ciente de que a saída pode conter sequências de escape e outro lixo devido ao shell do mongo esperar uma sessão interativa. lesslida com isso graciosamente.

Falcon Momot
fonte
12

Basta colocar os comandos que deseja executar em um arquivo, depois passá-los para o shell junto com o nome do banco de dados e redirecionar a saída para um arquivo. Portanto, se o seu comando find estiver find.jse o seu banco de dados estiver foo, terá a seguinte aparência:

./mongo foo find.js >> out.json
Adam Comerford
fonte
Isso não funcionou para mim, apenas imprimi a versão do shell e o nome do banco de dados para out.json. mongo foo < find.js > out.jsonfuncionou.
James Brown
1
esta resposta foi escrita antes de as ferramentas serem reescritas no Go e muitas versões atrás, a menos que você esteja usando algo muito antigo, provavelmente é por isso que não está funcionando para você
Adam Comerford
10

Coloque sua consulta (por exemplo db.someCollection.find().pretty()) em um arquivo javascript, digamos query.js. Em seguida, execute-o no shell do seu sistema operacional usando o comando:

mongo yourDb < query.js > outputFile

O resultado da consulta estará no arquivo denominado 'outputFile'.

Por padrão, o Mongo imprime os primeiros 20 documentos IIRC. Se você quiser mais, pode definir um novo valor para o tamanho do lote no shell do Mongo, por exemplo

DBQuery.shellBatchSize = 100.

JohnP
fonte
Este. Não seja mal direcionado por .jsextensão. Você pode escrever todas aquelas consultas de shell mongo sem alterá-las.
DC,
4

Usando printe JSON.stringifyvocê pode simplesmente produzir um resultado válido JSON .
Use o --quietsinalizador para filtrar o ruído do shell da saída.
Use --norcsinalizador para evitar .mongorc.jsavaliação. (Tive que fazer isso por causa de um formatador bonito que uso, que produz uma saída JSON inválida ) Use a DBQuery.shellBatchSize = ?substituição ?pelo limite do resultado real para evitar paginação.

E, finalmente, use teepara canalizar a saída do terminal para um arquivo:

// Shell:
mongo --quiet --norc ./query.js | tee ~/my_output.json

// query.js:
DBQuery.shellBatchSize = 2000;
function toPrint(data) {
  print(JSON.stringify(data, null, 2));
}

toPrint(
  db.getCollection('myCollection').find().toArray()
);

Espero que isto ajude!

Dmitry
fonte
2

Usando esta resposta de Asya Kamsky, escrevi um script de bat de uma linha para Windows. A linha se parece com esta:

mongo --quiet %1 --eval "printjson(db.%2.find().toArray())" > output.json

Então, pode-se executá-lo:

exportToJson.bat DbName CollectionName

margaretkru
fonte
2

Consegui salvar o resultado com a função writeFile () .

> writeFile("/home/pahan/output.txt", tojson(db.myCollection.find().toArray()))

A versão do shell do Mongo era 4.0.9

Pavel_H
fonte
1

Também há mongoexport para isso, mas não tenho certeza de qual versão está disponível.

Exemplo:

mongoexport -d dbname -c collection --jsonArray --pretty --quiet --out output.json
Neodan
fonte
0

Como resposta de Neodan, mongoexport é bastante útil com -qopção de consulta. Ele também converte ObjectIdpara o formato padrão de JSON "$oid". Por exemplo:

mongoexport -d yourdb -c yourcol --jsonArray --pretty -q '{"field": "filter value"}' -o output.json
Nhan D Le
fonte
0

você pode usar este comando para alcançá-lo:

mongo admin -u <userName> -p <password> --quiet --eval "cursor = rs.status(); printjson(cursor)" > output.json

Parimal Jana
fonte