Is there a way to 'pretty' print MongoDB shell output to a file?

Solution 1:

The shell provides some nice but hidden features because it's an interactive environment.

When you run commands from a javascript file via mongo commands.js you won't get quite identical behavior.

There are two ways around this.

(1) fake out the shell and make it think you are in interactive mode

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

or
(2) use Javascript to translate the result of a find() into a printable JSON

mongo dbname command.js > output.json

where command.js contains this (or its equivalent):

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

This will pretty print the array of results, including [ ] - if you don't want that you can iterate over the array and printjson() each element.

By the way if you are running just a single Javascript statement you don't have to put it in a file and instead you can use:

$ mongo --quiet dbname --eval 'printjson(db.collection.find().toArray())' > output.json

Solution 2:

Since you are doing this on a terminal and just want to inspect a record in a sane way, you can use a trick like this:

mongo | tee somefile

Use the session as normal - db.collection.find().pretty() or whatever you need to do, ignore the long output, and exit. A transcript of your session will be in the file tee wrote to.

Be mindful that the output might contain escape sequences and other garbage due to the mongo shell expecting an interactive session. less handles these gracefully.

Solution 3:

Just put the commands you want to run into a file, then pass it to the shell along with the database name and redirect the output to a file. So, if your find command is in find.js and your database is foo, it would look like this:

./mongo foo find.js >> out.json

Solution 4:

Put your query (e.g. db.someCollection.find().pretty()) to a javascript file, let's say query.js. Then run it in your operating system's shell using command:

mongo yourDb < query.js > outputFile

Query result will be in the file named 'outputFile'.

By default Mongo prints out first 20 documents IIRC. If you want more you can define new value to batch size in Mongo shell, e.g.

DBQuery.shellBatchSize = 100.

Solution 5:

Using print and JSON.stringify you can simply produce a valid JSON result.
Use --quiet flag to filter shell noise from the output.
Use --norc flag to avoid .mongorc.js evaluation. (I had to do it because of a pretty-formatter that I use, which produces invalid JSON output) Use DBQuery.shellBatchSize = ? replacing ? with the limit of the actual result to avoid paging.

And finally, use tee to pipe the terminal output to a file:

// 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()
);

Hope this helps!