Setting up MongoDB: Atlas, local install and mongosh

Choose between a local server, a container and Atlas, connect with mongosh, and get data in and out with CRUD, bulk writes and the import tools.

Local install, container or Atlas

OptionGood forWhat you take on
Local mongodDevelopment and offline workYou own backups, upgrades and disk
Docker with a volumeThrowaway and reproducible environmentsData lives in the volume, not the container
Atlas free or shared tierPrototypes and small projectsConnection limits and shared performance
Atlas dedicated clusterProductionCost, and a different feature set per tier
# macOS
brew tap mongodb/brew
brew install [email protected]
brew services start [email protected]

# Docker with a persistent volume
docker run -d --name mongo -p 27017:27017 \
  -v mongo-data:/data/db \
  -e MONGO_INITDB_ROOT_USERNAME=root \
  -e MONGO_INITDB_ROOT_PASSWORD=secret \
  mongo:8.0

# the shell
mongosh "mongodb://root:secret@localhost:27017/?authSource=admin"
mongosh "mongodb+srv://user:[email protected]/shop"
  • mongosh is the current shell and replaces the legacy mongo binary; the old shell does not support newer server features.
  • The connection string decides everything. authSource names the database the credentials live in, and mongodb+srv discovers the replica set members from DNS.
  • On Atlas, an IP access list entry is required before any connection succeeds. A timeout rather than an authentication error usually means the address is not allowlisted.
  • A replica set is not optional in practice: transactions and change streams both require one, and Atlas provides it by default.

CRUD from mongosh

use shop

db.orders.insertOne({
  customer: "Ada",
  total: NumberDecimal("19.90"),
  status: "new",
  placedAt: new Date()
})

db.orders.insertMany([
  { customer: "Grace", total: NumberDecimal("5.00"), status: "new" },
  { customer: "Linus", total: NumberDecimal("7.25"), status: "new" }
], { ordered: false })         // keep going after a failed document

db.orders.find({ status: "new" }).sort({ total: -1 }).limit(5)
db.orders.updateMany({ status: "new" }, { $set: { status: "queued" } })
db.orders.deleteMany({ status: "cancelled" })
db.orders.countDocuments({ total: { $gt: 10 } })
  • use shop switches the current database and creates it lazily on the first write.
  • ordered: false makes a bulk insert continue after a failure, and the returned error report lists exactly which documents were rejected.
  • NumberDecimal and new Date() build BSON values, not JavaScript ones. Storing a date as a string is the single most common way to break range queries later.
  • A find returns a cursor, not an array. In the shell a cursor is printed for you, but in code you must iterate it or call a terminal method.

Bulk writes and importing data

mongoimport --uri "mongodb://localhost:27017/shop" \
  --collection customers --file customers.json --jsonArray

mongoexport --uri "mongodb://localhost:27017/shop" \
  --collection orders --out orders.json

# run a script that seeds a development database
mongosh "mongodb://localhost:27017/shop" --file seed.js

# check without opening the shell
mongosh "mongodb://localhost:27017/shop" --eval 'db.orders.countDocuments()'
💡
Make every import idempotent: upsert on a natural key instead of inserting blindly, so re-running the same file repairs the state rather than duplicating it. Half-loaded collections are far more common than genuinely corrupted ones.

FAQ

Should I start on Atlas or locally?
Start locally if you want to learn the shell and the data model with no network in the way. Start on Atlas if you want a replica set from minute one, because transactions and change streams need one and you will otherwise hit that wall later.
Why does my connection time out instead of failing authentication?
A timeout is a network or firewall problem: an address missing from the Atlas access list, a container that cannot reach the host, or a DNS issue with an SRV record. A credential problem returns an authentication error quickly.

Documents, collections and queries Backup, restore and operational tooling

Last refreshed 2026-09-18.