MongoDB Cheatsheet

mongosh Basics

Use this MongoDB reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Connecting

mongosh is the shell. The legacy mongo shell was removed in MongoDB 6.0, so any snippet that starts with mongo is out of date. Everything below targets 8.0.

mongosh                                    # localhost:27017, "test" db
mongosh "mongodb://localhost:27017/shop"
mongosh "mongodb://app:secret@db1:27017/shop?authSource=admin"
mongosh "mongodb+srv://app@cluster0.ab12c.mongodb.net/shop"   # Atlas
mongosh --host db1 --port 27017 -u app -p --authenticationDatabase admin
mongosh "mongodb://a:27017,b:27017,c:27017/shop?replicaSet=rs0"
URI fragmentWhat it does
mongodb://Explicit host list, you name every node yourself
mongodb+srv://DNS seed list, one hostname resolves the whole cluster. Implies tls=true
?authSource=adminDatabase where the user is defined, not the data db. Missing it is the single most common auth failure
?replicaSet=rs0Lets the driver find the primary. Required for transactions and change streams
?retryWrites=trueRetry a failed write once. Default true on modern drivers
?readPreference=secondaryPreferredSend reads to secondaries
-p with no valuePrompt for the password instead of leaving it in shell history
--norcSkip ~/.mongoshrc.js
--nodbStart the shell without connecting to anything

Getting around

use switches database and does not require it to exist. A database and a collection spring into existence on the first write, never on use alone.

CommandResult
show dbsDatabases with size on disk. A database holding no data is not listed
use shopSwitch. Sets the db global
dbPrint the current database name
show collectionsCollections and views here
db.getCollectionNames()The same list as a JS array you can loop over
db.getSiblingDB("logs")Reach another database without leaving this one
db.help()Database-level methods
db.orders.help()Collection-level methods
db.orders. then TabComplete method names, and field names in recent versions
show users · show rolesAuth objects in the current db
exit or Ctrl-DLeave
use shop
db.orders.countDocuments()
db.getSiblingDB("logs").events.findOne()
db.adminCommand({ listDatabases: 1 })

BSON types you will actually type

The shell is JavaScript, so every bare number is a double. When the type matters you have to say so, and for money it always matters.

ConstructorBSON typeNotes
ObjectId()ObjectId12 bytes. The first 4 are a Unix timestamp, so ids sort roughly by creation time
ObjectId("65f...").getTimestamp()DateA free created_at, no extra field needed
ISODate("2026-01-15T09:30:00Z")DateMilliseconds since epoch, stored UTC
new Date()DateSame BSON type as ISODate
UUID()Binary, subtype 4For ids you want generated client side
NumberInt(7)int32
NumberLong("9007199254740993")int64Past 2⁵³ a double silently loses digits, so pass a string
NumberDecimal("19.99")decimal12834 significant digits, exact. The right type for money
BinData(0, "<base64>")Binary
/^ac/iRegexA native JS regex works as a query value
Timestamp(1, 1)TimestampInternal replication type, not a user-facing date
MinKey · MaxKeysentinelSort below and above every other value
// Wrong: binary floating point cannot represent most decimals
db.orders.insertOne({ total: 0.1 + 0.2 })      // stores 0.30000000000000004

// Right: decimal128, or plain integer minor units
db.orders.insertOne({ total: NumberDecimal("19.99") })
db.orders.insertOne({ total_cents: NumberInt(1999) })

ObjectId("65f1a2b3c4d5e6f701234567").getTimestamp()   // 2024-03-13T...

Reading output

A find() returns a cursor. mongosh prints the first 20 documents and then waits, and it pulls the next batch. Output is already pretty-printed, so .pretty() is a leftover from the old shell and buys you nothing.

db.orders.find()                  // prints 20, then: Type "it" for more
it                                // next batch

printjson(db.orders.findOne())
JSON.stringify(db.orders.findOne())    // BSON types collapse, ObjectId becomes {}
EJSON.stringify(db.orders.findOne())   // keeps them: {"$oid":"65f1..."}
EJSON.parse('{"_id": {"$oid": "65f1a2b3c4d5e6f701234567"}}')

config.set("displayBatchSize", 50)     // print 50 per batch instead of 20
config.set("inspectDepth", 8)          // stop deep documents printing as [Object]

Extended JSON is the wire-safe text form of BSON. Use EJSON any time output leaves the shell, because plain JSON.stringify destroys dates, decimals, and object ids.

Both query shapes take explain, and the noun order differs between them:

db.orders.find({ status: "paid" }).explain("executionStats")
db.orders.explain("executionStats").aggregate([{ $match: { status: "paid" } }])

Scripting

--eval for one expression, --file for a script, and load() from inside an interactive session. Both flags are repeatable and both exit when finished.

FlagDoes
--eval '<js>'Run an expression, print the result, exit
--file s.js / -f s.jsRun a script file and exit
--quietDrop the banner and connection chatter. Required for clean piping
--json / --json=canonicalEJSON on stdout, ready for jq
--eval + --file togetherFiles run first, then the eval expressions
mongosh "$URI" --quiet --eval 'db.orders.countDocuments({status:"paid"})'
mongosh "$URI" --quiet --json --eval 'db.orders.find().limit(5).toArray()' | jq .
mongosh "$URI" --file migrate-2026-01.js
// Inside the shell. Path is relative to the shell's working directory.
load("./seed.js")

// ~/.mongoshrc.js runs on every interactive start
config.set("displayBatchSize", 50);
prompt = () => `${db.getName()}> `;

Scripts are plain JavaScript, so await, for...of, and try/catch all work. Top-level await is supported, which matters because most driver methods return promises that mongosh normally awaits for you.