MongoDB stores data as documents — JSON-like objects with flexible structure. No fixed schema. No joins required for embedded data. This tutorial gets you up and running with MongoDB 8.0.

Setup with Docker

docker run -d \
  --name mongodb \
  -p 27017:27017 \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  mongodb/mongodb-community-server:8.0-ubi8

Connect with mongosh:

mongosh "mongodb://admin:password@localhost:27017"

mongosh Basics

// Show databases
show dbs

// Switch to (or create) a database
use myapp

// Show collections
show collections

// Create a collection explicitly (optional — auto-created on first insert)
db.createCollection("users")

Documents and Collections

In MongoDB:

  • A document is a JSON-like record (similar to a row in SQL)
  • A collection is a group of documents (similar to a table)
  • Every document has an _id field — auto-generated as an ObjectId if not provided
// A MongoDB document
{
  _id: ObjectId("64f1a2b3c4d5e6f7a8b9c0d1"),
  name: "Alex Johnson",
  email: "alex@example.com",
  age: 28,
  address: {
    city: "Berlin",
    country: "Germany"
  },
  tags: ["developer", "nodejs"],
  createdAt: ISODate("2026-01-15T10:00:00Z")
}

Insert

// Insert one document
db.users.insertOne({
  name: "Alex Johnson",
  email: "alex@example.com",
  age: 28
})

// Insert multiple documents
db.users.insertMany([
  { name: "Sam Lee", email: "sam@example.com", age: 32 },
  { name: "Jordan Kim", email: "jordan@example.com", age: 25 }
])

Find (Read)

// Find all documents
db.users.find()

// Find with filter
db.users.find({ age: { $gt: 25 } })

// Find one
db.users.findOne({ email: "alex@example.com" })

// Projection — include/exclude fields (1 = include, 0 = exclude)
db.users.find({}, { name: 1, email: 1, _id: 0 })

// Sort, limit, skip
db.users.find().sort({ age: -1 }).limit(10).skip(20)

Common query operators:

OperatorMeaningExample
$eqEquals{ age: { $eq: 28 } }
$neNot equals{ status: { $ne: "deleted" } }
$gt / $gteGreater than{ age: { $gte: 18 } }
$lt / $lteLess than{ price: { $lt: 100 } }
$inIn array{ status: { $in: ["active", "pending"] } }
$regexRegex match{ name: { $regex: /^Alex/i } }
$existsField exists{ phone: { $exists: true } }

Update

// Update one document
db.users.updateOne(
  { email: "alex@example.com" },
  { $set: { age: 29, updatedAt: new Date() } }
)

// Update many
db.users.updateMany(
  { age: { $lt: 18 } },
  { $set: { isMinor: true } }
)

// Upsert — insert if not found
db.users.updateOne(
  { email: "new@example.com" },
  { $set: { name: "New User", age: 20 } },
  { upsert: true }
)

Common update operators:

OperatorWhat it does
$setSet field value
$unsetRemove a field
$incIncrement a number
$pushAdd item to array
$pullRemove item from array
$addToSetAdd to array if not already present

Delete

// Delete one
db.users.deleteOne({ email: "alex@example.com" })

// Delete many
db.users.deleteMany({ createdAt: { $lt: ISODate("2020-01-01") } })

Node.js with Mongoose 8

Mongoose adds schema validation and a cleaner API on top of the MongoDB Node.js driver.

npm install mongoose
import mongoose, { Schema, Document } from "mongoose";

// Connect
await mongoose.connect("mongodb://admin:password@localhost:27017/myapp?authSource=admin");

// Define schema
const userSchema = new Schema({
  name:      { type: String, required: true },
  email:     { type: String, required: true, unique: true, lowercase: true },
  age:       { type: Number, min: 0 },
  tags:      [String],
  createdAt: { type: Date, default: Date.now },
});

const User = mongoose.model("User", userSchema);

// Create
const user = await User.create({
  name: "Alex Johnson",
  email: "alex@example.com",
  age: 28,
});

// Find
const users = await User.find({ age: { $gte: 18 } })
  .sort({ createdAt: -1 })
  .limit(10);

// Update
await User.findByIdAndUpdate(user._id, { age: 29 }, { new: true });

// Delete
await User.findByIdAndDelete(user._id);

Python with PyMongo

pip install pymongo
from pymongo import MongoClient
from datetime import datetime, timezone

client = MongoClient("mongodb://admin:password@localhost:27017/")
db = client["myapp"]
users = db["users"]

# Insert
result = users.insert_one({
    "name": "Alex Johnson",
    "email": "alex@example.com",
    "age": 28,
    "created_at": datetime.now(timezone.utc)
})
print(f"Inserted: {result.inserted_id}")

# Find
for user in users.find({"age": {"$gte": 18}}).sort("age", -1).limit(5):
    print(user["name"], user["age"])

# Update
users.update_one(
    {"email": "alex@example.com"},
    {"$set": {"age": 29}}
)

# Delete
users.delete_one({"email": "alex@example.com"})

client.close()

What’s Next?

You can now read and write data in MongoDB. Next: data modeling — the key skill that separates fast MongoDB apps from slow ones.

Next: Database Tutorial #10: MongoDB Data Modeling