Theory
The four things you do to data
Every database, relational or NoSQL, does the same 4 things to data: Create, Read, Update, Delete: CRUD. You did these with SQL in BCA205 (INSERT, SELECT, UPDATE, DELETE); MongoDB does them with methods on a collection.
The centrepiece is the query document: a little object that DESCRIBES which documents you want. find({ venue: "Ground" }) reads it as 'find events where venue equals Ground'. Master the query document and its $ operators, and FestConnect can fetch exactly the events it needs. This lesson is CRUD plus the query and projection tools that make reads powerful.
At a glance
MongoDB CRUD at a glance
| Operation | Method | Example |
|---|---|---|
| Create | insertOne / insertMany | db.events.insertOne({name:"Garba", seats:350}) |
| Read | find / findOne | db.events.find({venue:"Ground"}) |
| Update | updateOne / updateMany | db.events.updateOne({name:"Garba"}, {$set:{seats:300}}) |
| Delete | deleteOne / deleteMany | db.events.deleteOne({name:"Ghost"}) |
Theory
Read: query documents and operators
find(query, projection) is the workhorse.
The query document filters: find({}) returns ALL; find({ online: true }) returns only online events. For comparisons, use query operators (all start with $):
$gtgreater than,$ltless than,$gte/$lte,$nenot equal$in(value in a list),$and/$or
So find({ seats: { $gt: 100 } }) finds events with MORE than 100 seats.
Projection (the second argument) selects which FIELDS come back: find({}, { name: 1, _id: 0 }) returns only the name, hiding the _id. 1 includes a field, 0 excludes it; _id is included by default unless you exclude it.
Practical
CRUD on FestConnect events (predict the reads)
// CREATE
db.events.insertMany([
{ name: "Garba Night", seats: 350, online: false },
{ name: "Coding Contest", seats: 60, online: true },
{ name: "Webinar", seats: 500, online: true }
])
// READ: events with more than 100 seats, names only
db.events.find({ seats: { $gt: 100 } }, { name: 1, _id: 0 })
// -> { name: "Garba Night" }, { name: "Webinar" } (Coding Contest has 60)
// UPDATE: $set changes a field (NOT replace the document)
db.events.updateOne({ name: "Garba Night" }, { $set: { seats: 300 } })
// DELETE
db.events.deleteOne({ name: "Coding Contest" })
This example runs in Gri-Learn on the web, where you can edit it and see the output.
Theory
The $set trap in updates
The most dangerous CRUD mistake in MongoDB is updating WITHOUT $set.
updateOne({ name: "Garba Night" }, { $set: { seats: 300 } }) correctly changes ONLY the seats, leaving every other field intact.
But updateOne({ name: "Garba Night" }, { seats: 300 }) (no $set) REPLACES the entire matched document with { seats: 300 }: the name, venue, tags: everything else is DELETED, and now the document has only a seats field. This is a silent data-destroying bug. The rule: to change fields, ALWAYS use an update OPERATOR like $set; a bare object replaces the whole document. $set to modify, $inc to increment, $push to add to an array.
Quiz
db.events.updateOne({name:"Garba"}, {seats: 300}) is run WITHOUT $set. What happens to the Garba document?
- Only the seats field changes to 300; other fields stay
- The entire document is REPLACED by {seats: 300}: name, venue and all other fields are lost
- It throws an error requiring $set
- Nothing changes
Show the answer
The entire document is REPLACED by {seats: 300}: name, venue and all other fields are lost
Without an update operator like $set, MongoDB treats {seats: 300} as a full REPLACEMENT document, so the matched Garba document is overwritten to contain ONLY seats: its name, venue, tags and everything else are destroyed. This is a notorious silent data-loss bug. Option A describes what $set WOULD do ({$set:{seats:300}}), which is what you almost always want. Option C is wrong: MongoDB does NOT error; it quietly replaces, which is what makes the bug dangerous. Option D is false: it very much changes the document. The rule burned in by this trap: to modify fields, always use $set (or another operator); a bare object replaces the whole document.
Think first
Trace the find
After the insertMany in the listing (Garba 350, Coding 60, Webinar 500), work out exactly what db.events.find({ seats: { $gt: 100 } }, { name: 1, _id: 0 }) returns. Then tap.
Show the answer
The query { seats: { $gt: 100 } } matches events with MORE than 100 seats: Garba Night (350) YES, Coding Contest (60) NO, Webinar (500) YES. So 2 documents match. The projection { name: 1, _id: 0 } returns ONLY the name field and hides _id. Result: { name: "Garba Night" } and { name: "Webinar" }. Coding Contest is excluded by the query (60 is not > 100), and every field except name is hidden by the projection. Reading a MongoDB find is always these 2 steps: the query document decides WHICH documents, the projection decides WHICH fields of them. Trace both and the output is exact.
Watch out
CRUD traps
Update without $set: replaces the whole document, destroying other fields; always use $set (or $inc, $push).
deleteMany({}): an empty filter matches EVERYTHING; deleteMany({}) wipes the collection: be careful.
updateOne vs updateMany: updateOne changes only the FIRST match; use updateMany for all matches.
Projection mixing: you generally either include fields (1s) or exclude (0s), not both (except _id:0 alongside includes).
Forgetting quotes on string values: find({venue: Ground}) errors; it is find({venue: "Ground"}).
Theory
CRUD done; now shape the results
FestConnect can now create, read, update and delete events, and filter reads with query operators and projection. The final Unit 1 lesson goes further: operators for projection, updating, limiting and sorting results, plus the AGGREGATION pipeline, MongoDB's tool for summarising data (counting registrants per event, totalling seats). Then the unit shifts to building the modern UI on this data with React.
Summary
Key takeaways
- CRUD: insertOne/insertMany (create), find/findOne (read), updateOne/updateMany (update), deleteOne/deleteMany (delete).
- The query document filters reads: find({online:true}); query operators start with $ ($gt, $lt, $ne, $in, $or).
- find({seats:{$gt:100}}) finds events with more than 100 seats.
- Projection (find's 2nd argument) selects fields: {name:1, _id:0} returns only name; 1 includes, 0 excludes.
- Update with $set to change a field; a bare object (no $set) REPLACES the whole document, destroying other fields.
- deleteMany({}) with an empty filter deletes everything: handle with care.
- Memory hook: query document picks the documents, projection picks the fields, $set changes without replacing.