Internet Engineering

MongoDB

NoSQL · Distribution · MongoDB · Documents · Operations

Fall 2026 · Amirkabir University of Technology
@1995parham

Introduction to NoSQL and MongoDB

Originally presented by Ehsan Edalat and Parham Alvani. The original slides are also available as a PowerPoint file.

Why NoSQL?

  • The relational model asks you to know the schema up front, and to normalise data across tables
  • That is a good fit for many problems, and a poor one when
    • documents differ from each other in shape
    • the data does not fit on a single machine
    • reads dominate, and joins get expensive
  • NoSQL is not one database, it is a family of trade-offs

Taxonomy

  • Key-Value: a hash table, e.g. Redis
  • Document: self-describing records, e.g. MongoDB
  • Column Family: wide sparse rows, e.g. Cassandra
  • Graph: nodes and edges as first-class things, e.g. Neo4j

Questions to Ask

  • Data model: are your records rows, documents, or a graph?
  • Scalability: does the data fit on one server, now and later?
  • Transactions: do a set of operations need to succeed or fail together?
  • Query: do you know the access patterns in advance?

The CAP Theorem

  • In the presence of a network partition, a distributed system must choose between
    • Consistency: every read sees the latest write
    • Availability: every request gets an answer
  • Partitions are not optional, so the real choice is what to do when one happens

Replica Sets

The same data on several servers. If the primary disappears, the members elect a new one, so failover needs no operator.

An application sends writes to the primary mongod. Two secondaries copy the primary's oplog and replay it asynchronously; all members exchange heartbeats every 2 seconds. A write sent to a secondary fails with NotWritablePrimary. If the primary is silent for 10 seconds, a secondary calls an election, a majority (2 of 3) votes, and it becomes the new primary

Sharding

Horizontal scale: one logical database split by a shard key. A poor key sends every query to every shard, or every write to one shard.

The application talks to mongos, the router, which looks up ranges in the config servers. Shard A holds MinKey to H, shard B H to P, shard C P to MaxKey, each a replica set. A query on the shard key, find name Sara, goes to shard C only; a query on capacity goes to every shard

What is MongoDB?

  • A document-oriented database, first released in 2009
  • Documents are stored as BSON, a binary form of JSON with more types
    • Dates, 32/64-bit numbers, and binary data, which JSON lacks
  • Secondary indexes, an aggregation pipeline, and a query language

Hierarchy

  • A server holds zero or more databases
  • A database holds zero or more collections
  • A collection holds zero or more documents

Coming From SQL

RDBMSMongoDB
DatabaseDatabase
Table, ViewCollection
RowDocument (BSON)
ColumnField
IndexIndex
JoinEmbedding, or $lookup
Primary key_id

Processes

  • mongod: the database server
  • mongos: the router in front of a sharded cluster
  • mongosh: the shell, a full JavaScript environment

Schema Free?

  • MongoDB does not require a schema, and two documents in one collection may differ
  • But the data still has a schema. The question is only whether the database or your application enforces it
  • Schema validation exists when you want the database to check

{ "_id": 1, "name": "R2-D2", "race": "Droid", "affiliation": "rebels" }
{ "_id": 2, "name": "Han Solo", "ship": "Millennium Falcon" }
    

Embed or Reference?

Model for the queries you will run, not for the tidiest normal form.

Left: the course as three relational tables, courses, enrollments and students, linked by course_id and student_id, so one read needs a join over three. Right: the same course as one MongoDB document with the students array embedded. Embed what you read together; reference what grows without bound or is shared by many documents

CRUD


// create
db.students.insertOne({ name: "Parham", id: "9231058" });
db.students.insertMany([{ name: "Ali" }, { name: "Sara" }]);

// read
db.students.find({ name: "Parham" });
db.students.findOne({ id: "9231058" });

// update
db.students.updateOne({ id: "9231058" }, { $set: { name: "Parham Alvani" } });

// delete
db.students.deleteOne({ id: "9231058" });
    

Aggregation Pipeline

Documents flow through stages, each one transforming the stream.


// keep the big courses, count them per teacher, busiest first
db.courses.aggregate([
  { $match: { capacity: { $gt: 20 } } },
  { $group: { _id: "$teacher", total: { $sum: 1 } } },
  { $sort: { total: -1 } },
]);
    

Aggregation Pipeline (Cont.)

Eight course documents enter. $match capacity greater than 20 drops C and Lab, leaving six. $group by teacher gives Rahimi 1, Alvani 3, Karimi 2 in no particular order. $sort total descending gives Alvani 3, Karimi 2, Rahimi 1

Transactions

  • A single document write is atomic, which covers most cases if you embed well
  • Multi-document ACID transactions exist since MongoDB 4.0
  • They cost more than in a relational database, so they are a tool rather than a default

Mongoose

  • An ODM for Node.js: schemas, validation, and models over the driver
  • Puts the schema back, in the application layer

const studentSchema = new mongoose.Schema({
  name: { type: String, required: true },
  id: { type: String, unique: true },
});

const Student = mongoose.model("Student", studentSchema);
    

References 📚

Fork me on GitHub