Back to Database Instructions
Getting Started · Databases

Install MongoDB

MongoDB is a database server that stores documents, which are records that look like JSON objects, instead of rows in tables. You don't design a table first: you hand it a document and it stores whatever fields that document has. This page installs the free Community edition on Linux, macOS, or Windows, connects the mongosh shell, and has you insert, find, update, and delete your first documents. Follow the step for your operating system, skip the other two, and pick up again at Step 05.

The finish line — what you'll see when it's done
$ mongosh test> use shop shop> db.people.find({}, { _id: 0 }) [ { name: 'Ada', city: 'London', age: 36 }, { name: 'Linus', city: 'Portland', age: 21 } ]
Current release MongoDB 8.3
This guide has a few 💡 Explain it simply prompts. When you reach one, answer it out loud in plain words before revealing the answer. MongoDB's flexibility is what makes it quick to start with and also what gets people into trouble later, and explaining it is the best way to understand both.
STEP 01

Know what you're installing.

A MongoDB install has two programs you'll use:

  • mongod: the server, short for mongo daemon. It runs in the background, owns a data directory, and listens on port 27017.
  • mongosh: the MongoDB Shell, a command line where you type queries. It's a full JavaScript environment, so queries are method calls like db.people.find() and not SQL.

The data is nested three levels deep. A server holds databases; a database holds collections, which play the part of tables; a collection holds documents, which play the part of rows. Two documents in the same collection don't need the same fields.

Which version

This page installs MongoDB 8.3 (8.3.11 as of this writing). MongoDB publishes a major version about once a year, currently 8.0, and minor releases such as 8.3 in between. Everything from Step 05 onward works the same on 7.0 or any 8.x. The free edition is called Community; Enterprise and the hosted Atlas service are the paid versions.

A server that stores documents, and a shell that speaks JavaScript to it.

STEP 02

Linux — MongoDB's own apt repository.

Ubuntu doesn't package MongoDB at all, because of its license, so you add MongoDB's own repository. MongoDB 8.3 supports Ubuntu 24.04, 22.04, and 20.04 LTS on x86_64 and ARM64. First trust the key that signs the packages, then add the repository:

terminal — add the repositorytwo commands
# 1. download the signing key (8.3 packages are signed with the 8.0 key)
curl -fsSL https://pgp.mongodb.com/server-8.0.asc | \
   sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor

# 2. add the repository — on 22.04 change noble to jammy
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.3 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.3.list

Then install it. The mongodb-org package pulls in the server, mongosh, and the backup tools:

terminal — install and startthree commands
sudo apt update
sudo apt install -y mongodb-org
sudo systemctl enable --now mongod

Unlike PostgreSQL, the package doesn't start the server for you. enable --now starts it now and at every boot. Check it's running:

systemctl is-active mongod
active

The data lives in /var/lib/mongodb and the log in /var/log/mongodb/mongod.log. Jump to Step 05.

Debian, RHEL, and friends

MongoDB publishes the same kind of repository for Debian (apt) and for RHEL, Rocky, Alma, and Amazon Linux (dnf). The Linux install page has the exact lines for each. It doesn't support Fedora or Arch; on those, run it in Docker with docker run -d -p 27017:27017 mongo:8.

STEP 03

macOS — MongoDB's Homebrew tap.

MongoDB isn't in Homebrew's main catalogue either, for the same license reason. MongoDB publishes its own tap, a third-party formula repository, and Homebrew needs you to trust a tap before it will load its formulas:

terminal — Homebrewfour commands
# add MongoDB's tap and mark it as trusted (once per machine)
brew tap mongodb/brew
brew trust mongodb/brew

# install the server, mongosh, and the tools, then start it
brew install mongodb-community@8.3
brew services start mongodb-community@8.3

brew services starts the server now and at every login. On Apple Silicon the data goes in /opt/homebrew/var/mongodb and the config in /opt/homebrew/etc/mongod.conf; Intel Macs use /usr/local instead of /opt/homebrew. MongoDB 8.3 needs macOS 14 Sonoma or later.

If macOS blocks mongod

If you get a warning that the developer couldn't be verified, open System Settings → Privacy & Security, scroll to the message about mongod, and click Open Anyway. Then run the brew services start line again.

STEP 04

Windows — the .msi installer, plus mongosh.

MongoDB 8.3 supports 64-bit Windows 11 and Windows Server 2022. Download the installer from the MongoDB Download Center: choose version 8.3, platform Windows, package msi. Run it and choose Complete, then keep the defaults on the next screen:

  • Install MongoD as a Service: leave it ticked, running as Network Service. The server then starts with Windows, like PostgreSQL does.
  • Data and log directories: the defaults, under C:\Program Files\MongoDB\Server\8.3\, are fine.
  • Install MongoDB Compass: optional. Compass is a graphical browser for your data and is worth having later.

The installer doesn't include mongosh. Install it separately; winget is quickest:

PowerShell — winget
winget install MongoDB.Shell

winget install MongoDB.Server can install the server too, with no wizard. If you use it, open Services afterwards and check there's a MongoDB entry that's Running. Either way, close PowerShell and open a new window so mongosh is on your PATH.

Not inside WSL

MongoDB doesn't support running the server inside Windows Subsystem for Linux. Install it on the Windows side as above, and run mongosh from PowerShell.

STEP 05

Verify it, and read the warning.

Connect the shell to the server. With no arguments, mongosh connects to the server on your own machine on port 27017:

mongosh
Current Mongosh Log ID: 6ab543db8e2eb6b57eee51fc Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.12.0 Using MongoDB: 8.3.11 Using Mongosh: 2.12.0 ------ The server generated these startup warnings when booting ...: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted ------ test>

The two Using lines show the server and shell versions. test> is the prompt: test is the database you're currently in. MongoDB connects you to one called test by default, even though it doesn't exist yet.

There may be several startup warnings, depending on your system, but one of them matters: access control is not enabled. A fresh MongoDB has no users and no passwords, and anyone who can reach port 27017 can read and delete everything. That's safe for now only because the server listens on 127.0.0.1, meaning your own machine, and nowhere else. Step 08 covers what to do before that changes.

If it says ECONNREFUSED

The shell works but no server is listening. Start it with sudo systemctl start mongod on Linux or brew services start mongodb-community@8.3 on macOS. On Windows, start the MongoDB service in Services. On Linux, if it won't stay up, the reason is at the end of /var/log/mongodb/mongod.log.

STEP 06

Your first documents.

Switch to a database called shop. It doesn't exist, and that's fine: MongoDB creates databases and collections the first time you write to them.

use shop
switched to db shop

Insert one document into a collection called people. It's a JavaScript object: keys don't need quotes, and strings can use either kind of quote.

mongosh — insert one
db.people.insertOne({ name: "Ada", city: "London", age: 36 })
{ acknowledged: true, insertedId: ObjectId('6ab543d4263d934188d384a2') }

You didn't give it an id, so MongoDB made one: every document gets an _id field, and if you leave it out it's filled in with an ObjectId. Your ids will be different from the ones shown here, because an ObjectId is built partly from the current time. Now insert two more at once, and notice Grace has a field the others don't:

mongosh — insert many4 lines
db.people.insertMany([
  { name: "Linus", city: "Helsinki", age: 21 },
  { name: "Grace", city: "New York", age: 45, languages: ["COBOL", "FLOW-MATIC"] }
])
{ acknowledged: true, insertedIds: { '0': ObjectId('6ab543d4263d934188d384a3'), '1': ObjectId('6ab543d4263d934188d384a4') } }

Read everything back. The second argument is a projection, which picks the fields to return; { _id: 0 } hides the ids to keep the output short:

db.people.find({}, { _id: 0 })
[ { name: 'Ada', city: 'London', age: 36 }, { name: 'Linus', city: 'Helsinki', age: 21 }, { name: 'Grace', city: 'New York', age: 45, languages: [ 'COBOL', 'FLOW-MATIC' ] } ]

The first argument is the filter. The empty {} means “everything”. A filter is itself a document describing what to match, and operators such as $gt (greater than) start with a dollar sign. This is the same query as the PostgreSQL guide's WHERE age > 30 ORDER BY age DESC:

db.people.find({ age: { $gt: 30 } }, { _id: 0, name: 1, age: 1 }).sort({ age: -1 })
[ { name: 'Grace', age: 45 }, { name: 'Ada', age: 36 } ]
STEP 07

Update, delete, and count.

updateOne takes a filter and a change. $set changes just the fields you name and leaves the rest of the document alone. Without it, you'd be replacing the whole document.

mongosh — update
db.people.updateOne({ name: "Linus" }, { $set: { city: "Portland" } })
{ acknowledged: true, insertedId: null, matchedCount: 1, modifiedCount: 1, upsertedCount: 0 }

matchedCount is how many documents the filter found; modifiedCount is how many actually changed. If the two differ, the value you set was already there. Delete works the same way:

db.people.deleteOne({ name: "Grace" })
db.people.countDocuments()
{ acknowledged: true, deletedCount: 1 } 2

The One in updateOne and deleteOne means they act on the first match and stop. updateMany and deleteMany act on every match, and deleteMany({}) with an empty filter empties the collection, so be careful with it.

💡 Explain it simply

Grace had a languages field that nobody else had, and MongoDB accepted it without complaint. Now suppose a typo inserts { name: "Ken", citty: "Berkeley" }. Explain what MongoDB does, and what PostgreSQL would have done.

Reveal a plain-language answer

MongoDB stores it happily, with a field called citty, because it has no list of which fields are allowed. The mistake only shows up later, when a search for Ken's city comes back empty. PostgreSQL would have refused the insert on the spot, since its table has no column called citty. That's the trade-off: MongoDB lets you add fields without planning, and in return the checking becomes your code's job. If you want MongoDB to check, you can attach a schema validator to a collection, which brings back some of the rules a table gives you for free.

STEP 08

Find your way around, and lock it down.

A few shell commands aren't JavaScript. They're shortcuts built into mongosh:

CommandWhat it does
show dbsList databases and their size on disk
use nameSwitch database (it's created on the first write)
show collectionsList collections in the current database
db.people.createIndex({ name: 1 })Index a field so lookups on it don't scan the whole collection
db.people.drop()Delete a whole collection
helpList shell commands; db.people.help() lists collection methods
exitQuit (Ctrl+D works too)
show dbs
admin 8.00 KiB config 12.00 KiB local 8.00 KiB shop 8.00 KiB

The sizes on yours will differ. admin, config, and local are MongoDB's own; leave them alone.

Before anything but your laptop can reach it

Two settings in mongod.conf keep an unsecured server safe: net.bindIp, which is 127.0.0.1 by default, and security.authorization, which is off by default. Before you change bindIp so other machines can connect, create an admin user and turn authorization: enabled on. MongoDB's Enable Access Control page takes about five minutes. Open, passwordless MongoDB servers on the internet are found and wiped by automated scanners, usually within hours.

Localhost and no password is a fine way to learn. It's not a way to deploy.

STEP 09

Where to go next.

You have a server, a shell, and a collection you've inserted into, queried, updated, and deleted from. Your programs connect with a URL made of the same pieces the shell printed: mongodb://127.0.0.1:27017/shop. Every major language has an official MongoDB driver that accepts it.

1

Install PostgreSQL

The same people table in a relational database, for comparison: a schema first, then SQL, with the server enforcing the rules.

2

SQLite3 Complete Guide

Learn SQL properly with no server to run. Useful even if you stay with MongoDB, because most data work eventually meets SQL.

3

Database Instructions

Back to the index, with a side-by-side table of SQLite, PostgreSQL, and MongoDB.