How to export a MongoDB collection to JSON or CSV
Export a MongoDB collection to JSON or CSV with mongoexport, filter with --query, keep data types intact, and know what CSV silently loses.
Quick Answer
JSON exports every field. CSV needs a field list:
# one JSON document per line
mongoexport --uri="mongodb://localhost:27017/shop" --collection=orders --out=orders.json
# CSV with chosen columns
mongoexport --uri="mongodb://localhost:27017/shop" --collection=orders \
--type=csv --fields=_id,total,createdAt,customer.city --out=orders.csv
If you're moving data to another MongoDB, use mongodump instead. mongoexport is for getting data out of MongoDB, into spreadsheets, scripts or other systems.
Filter, sort and limit the export
mongoexport --uri="$URI/shop" -c orders \
--query='{"status":"paid","createdAt":{"$gte":{"$date":"2026-01-01T00:00:00Z"}}}' \
--sort='{"createdAt":-1}' --limit=1000 --out=recent_paid.json
--query takes Extended JSON, not mongosh syntax, so dates are {"$date": "…"} and ObjectIds are {"$oid": "…"}. Wrap the query in single quotes so your shell leaves the $ signs alone. On Windows cmd, use double quotes outside and escape the inner ones.
| Flag | Effect |
|---|---|
--fields=a,b.c | Only these fields (dotted paths reach into embedded documents) |
--jsonArray | Write one JSON array instead of one document per line |
--pretty | Indent the JSON (pair with --jsonArray for a readable file) |
--jsonFormat=canonical | Keep every BSON type in the output (see below) |
--noHeaderLine | CSV without the header row |
JSON or CSV?
| JSON (default) | CSV | |
|---|---|---|
| Needs --fields | No | Yes |
| Nested documents | Kept as objects | Squashed into a JSON string in one cell |
| Arrays | Kept | A JSON string in one cell |
| Types on re-import | Mostly kept (fully with canonical) | Lost: everything becomes a string or a number |
| Opens in Excel | No | Yes |
Choose CSV for people and spreadsheets, and JSON for anything a program will read or re-import. For exports that run every night, see automating MongoDB exports, imports and sync jobs.
What we found testing this
Setup: 50,000 orders with Decimal128 totals, NumberLong quantities, Date timestamps, embedded customer documents, arrays and ObjectId references, on MongoDB 7.0 in Docker on an Apple-silicon Mac.
1. A date written as a string in --query exports nothing, without an error
$ mongoexport -c orders --query='{"createdAt":{"$gte":"2026-01-20T00:00:00Z"}}' --out=q.json
exported 0 records
$ mongoexport -c orders --query='{"createdAt":{"$gte":{"$date":"2026-01-20T00:00:00Z"}}}' --out=q.json
exported 22640 records
A string never compares equal to a date in MongoDB, so the first query matches nothing. Always wrap dates in $date.
2. The default JSON quietly changes NumberLong to int
The default "relaxed" format writes small numbers as plain JSON numbers. After exporting and importing all 50,000 documents again, every qty that had been long came back as int:
| Export format | File size | qty type after re-import |
|---|---|---|
| Default (relaxed) | 10.8 MB | int for all 50,000 |
--jsonFormat=canonical | 13.0 MB | long for all 50,000 |
Decimal128, Date and ObjectId survived both formats. If types matter on the way back in (money, IDs, counters that can exceed 2³¹), use canonical. It's about 20% bigger.
3. CSV turns every special type into text
Exported to CSV and imported again with --headerline, one document looked like this:
{"_id":3,"total":3.3,"createdAt":"2026-01-01T00:03:00.000Z","customer":{"city":"NYC"},"ref":"ObjectId(6ae0ff23edb63f4f768177a7)"}
- The
Decimal128total became a floating-point number. - The date became a string, so date range queries stop working.
- The ObjectId became the literal text
"ObjectId(…)", not even the bare hex. - The dotted column
customer.citywas turned back into an embedded document.
4. The CSV error is short and doesn't say which flag
$ mongoexport -c orders --type=csv --out=o.csv
Failed: CSV mode requires a field list
The fix is --fields=a,b,c, or --fieldFile=fields.txt with one field per line.
5. Indexes aren't exported
After re-importing either JSON file, the new collection had only the _id index. mongoexport writes documents and nothing else, so recreate indexes yourself, or use mongodump, which saves index definitions.
Export every collection
mongoexport handles one collection per run. To export a whole database as JSON, loop over the collection names:
for c in $(mongosh "$URI/shop" --quiet --eval 'db.getCollectionInfos({type:"collection"}).map(c=>c.name).filter(n=>!n.startsWith("system.")).join(" ")'); do
mongoexport --uri="$URI/shop" -c "$c" --jsonFormat=canonical --out="export/$c.json"
done
The filter matters. A plain db.getCollectionNames() loop also exported system.views, and exported each view's results as if they were a collection (16,667 documents for our ny_orders view).
For a full copy you plan to restore into MongoDB, a single mongodump --archive is simpler and keeps indexes and views.
Frequently Asked Questions
How do I export a MongoDB collection to CSV?
Run mongoexport with --type=csv and a --fields list, for example mongoexport -c orders --type=csv --fields=_id,total,createdAt --out=orders.csv.
Can mongoexport export nested fields to separate CSV columns?
Yes, list them with dot notation, such as --fields=customer.name,customer.city. A field you list as a whole embedded document becomes one cell containing JSON.
What is the difference between mongoexport and mongodump?
mongoexport writes JSON or CSV for other tools and loses indexes and some types. mongodump writes BSON with index definitions and is the right tool for backups and moving data between MongoDB servers.
Can I export the result of an aggregation?
Not directly; mongoexport takes a find-style --query. Write the aggregation result to a collection with $out, then export that collection.