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.
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.
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.
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:
# 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:
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
The data lives in /var/lib/mongodb and the log in /var/log/mongodb/mongod.log. Jump to Step 05.
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.
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:
# 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 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.
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:
C:\Program Files\MongoDB\Server\8.3\, are fine.The installer doesn't include mongosh. Install it separately; winget is quickest:
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.
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.
Connect the shell to the server. With no arguments, mongosh connects to the server on your own machine on port 27017:
mongosh
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.
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.
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
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.
db.people.insertOne({ name: "Ada", city: "London", age: 36 })
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:
db.people.insertMany([
{ name: "Linus", city: "Helsinki", age: 21 },
{ name: "Grace", city: "New York", age: 45, languages: ["COBOL", "FLOW-MATIC"] }
])
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 })
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 })
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.
db.people.updateOne({ name: "Linus" }, { $set: { city: "Portland" } })
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()
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.
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.
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.
A few shell commands aren't JavaScript. They're shortcuts built into mongosh:
| Command | What it does |
|---|---|
show dbs | List databases and their size on disk |
use name | Switch database (it's created on the first write) |
show collections | List 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 |
help | List shell commands; db.people.help() lists collection methods |
exit | Quit (Ctrl+D works too) |
show dbs
The sizes on yours will differ. admin, config, and local are MongoDB's own; leave them alone.
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.
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.
The same people table in a relational database, for comparison: a schema first, then SQL, with the server enforcing the rules.
Learn SQL properly with no server to run. Useful even if you stay with MongoDB, because most data work eventually meets SQL.
Back to the index, with a side-by-side table of SQLite, PostgreSQL, and MongoDB.