Quick Answer

CRUD means Create, Read, Update, and Delete — the four basic things you do with data. In MongoDB you run these on a collection of documents using the mongo shell: insertOne/insertMany to add data, find to read it, updateOne/updateMany with $set to change it, and deleteOne/deleteMany to remove it. Documents are flexible JSON-like objects, so unlike SQL rows they don't have to share the same fixed columns.

What are MongoDB CRUD operations?

CRUD stands for Create, Read, Update, and Delete — the four things you do with almost any database. Learning the core MongoDB CRUD operations means learning how to add data, fetch it back, change it, and remove it. Once these four click, most of MongoDB starts to make sense.

MongoDB stores data as documents inside collections. A document is a JSON-like object (technically BSON, a binary form of JSON), and a collection is just a group of documents — think of it as roughly like a table, but far more relaxed about structure.

In this tutorial we will build a small users collection and run every operation ourselves in the mongo shell. Each example is short and actually works, so you can type along and see the output.

Setting up: the mongo shell and a users collection

The mongo shell (the newer version is called mongosh) is an interactive prompt where you type JavaScript-style commands. Start it by running mongosh in your terminal after MongoDB is installed and running.

First, pick a database. You do not have to create it in advance — MongoDB makes it the moment you write data into it:

use school
// switched to db school

Now every command uses db to mean the school database, and db.users means the users collection inside it. You do not need to create the collection first either; inserting the first document creates it automatically.

A quick note on _id: every document gets a unique _id field. If you do not supply one, MongoDB generates an ObjectId for you — a 12-byte value that is unique across the collection. This is the closest thing MongoDB has to a primary key.

Create: insertOne and insertMany

To add a single document, use insertOne. Pass it one object:

db.users.insertOne({
  name: "Aarav",
  email: "aarav@example.com",
  age: 21,
  city: "Pune"
})

MongoDB replies with acknowledged: true and the generated insertedId (the _id). To add several documents at once, use insertMany and pass an array:

db.users.insertMany([
  { name: "Diya",  email: "diya@example.com",  age: 24, city: "Mumbai" },
  { name: "Rohan", email: "rohan@example.com", age: 19, city: "Delhi" },
  { name: "Meera", email: "meera@example.com", age: 27, city: "Delhi", country: "India" }
])

Look closely at Meera: she has a country field the others do not. MongoDB is completely fine with that. Each document can carry its own set of fields — there is no shared column list to update first. This flexibility is one of the biggest differences from SQL, and we will come back to it.

Gotcha: insertMany stops at the first failing document by default (for example, a duplicate _id). If you want it to keep going and insert the rest, pass { ordered: false } as a second argument.

Read: find and query filters

Reading is where you will spend most of your time. find returns documents that match a filter. With no filter, it returns everything:

db.users.find()

Pass an object to filter by an exact match. This returns every user in Delhi:

db.users.find({ city: "Delhi" })

Need only one result? findOne returns the first match as a single document instead of a cursor:

db.users.findOne({ email: "aarav@example.com" })

Comparison operators

For anything beyond exact matches, MongoDB uses operators that start with $. To find users older than 20:

db.users.find({ age: { $gt: 20 } })

Common ones: $gt (greater than), $gte (greater than or equal), $lt, $lte, $ne (not equal), and $in (matches any value in a list):

db.users.find({ age: { $in: [19, 21] } })

Choosing which fields to return

The second argument to find is a projection — it picks which fields come back. Use 1 to include and 0 to exclude. Here we ask for just the name and hide the _id:

db.users.find({ city: "Delhi" }, { name: 1, _id: 0 })

Tip: add .pretty() to make output easier to read, for example db.users.find().pretty().

Update: updateOne, updateMany, and $set

Updates need two parts: a filter (which documents to change) and an update (what to change). The most common update operator is $set, which changes specific fields and leaves the rest alone.

updateOne changes only the first matching document. Move Aarav to Bengaluru:

db.users.updateOne(
  { name: "Aarav" },
  { $set: { city: "Bengaluru" } }
)

updateMany changes every match. Add a country field to all Delhi users:

db.users.updateMany(
  { city: "Delhi" },
  { $set: { country: "India" } }
)

If the field does not exist yet, $set creates it — that is how we just added country to documents that never had it. Other handy operators include $inc to add to a number and $unset to remove a field:

db.users.updateOne(
  { name: "Diya" },
  { $inc: { age: 1 } }
)

Big gotcha — always use $set. If you pass a plain object without an update operator, older drivers would replace the entire document, wiping every field you did not mention. Modern mongosh protects you by throwing an error instead, but the habit to build is simple: use $set when you mean "change these fields". If you truly want to swap a whole document, use the clearly named replaceOne.

Delete: deleteOne and deleteMany

Deleting works like reading — you pass a filter, and matching documents are removed. deleteOne removes the first match:

db.users.deleteOne({ name: "Rohan" })

deleteMany removes every match. Remove all users in Delhi:

db.users.deleteMany({ city: "Delhi" })

Both return a deletedCount so you can confirm how many documents were removed.

The most dangerous command in this tutorial:

db.users.deleteMany({})   // deletes EVERY document in the collection

An empty filter {} matches all documents, so this empties the whole collection. There is no undo. Before running any deleteMany, run the same filter with find first and check the results are exactly what you expect. This one habit will save you from a lot of pain.

How documents differ from SQL rows

If you have used MySQL or another SQL database, MongoDB documents will feel familiar but freer. A SQL table forces every row to share the same fixed columns. A MongoDB collection lets each document carry whatever fields it needs — like our user Meera having a country field the others did not.

CapabilitySQL rowMongoDB document
Fixed columns enforced up frontYesNo
Add a field to one record onlyNoYes
Store a nested object or list inside a recordPartialYes
Built-in unique identifierYesYes

A few practical takeaways:

  • Fields, not columns. Documents hold key-value fields. Missing a field just means it is not there — no NULL placeholder is required.
  • Nesting is natural. A document can contain arrays and other objects directly, so data that would need several joined tables in SQL often lives in one document.
  • The _id is your key. It plays the role of a primary key and is indexed automatically.
  • Flexibility is a responsibility. Because nothing forces a shape, your application code should stay consistent about which fields it writes, or your data can drift over time.

Recommendation and next steps

Practice beats reading. Open mongosh, build the users collection above, and run each command yourself. A good order to internalize is exactly CRUD: insert some data, find it with a few different filters, update it with $set, then delete carefully.

My clear recommendation for beginners: always preview destructive commands with find first, and always reach for $set on updates. Those two habits prevent the mistakes that trip up almost everyone early on. Once basic CRUD feels natural, your next steps are indexes (for fast queries on large collections), the aggregation pipeline (for grouping and reporting), and using a driver like the Node.js or Python client so your app can run these same operations in code.

Want a structured path with more examples and exercises? Our free MongoDB course walks through everything here and goes further into schema design, indexing, and aggregation. It is free, like everything on Priodemy.

Frequently Asked Questions

What does CRUD stand for in MongoDB?

CRUD stands for Create, Read, Update, and Delete — the four basic operations you perform on data. In MongoDB these map to insert commands (insertOne, insertMany), find, update commands (updateOne, updateMany), and delete commands (deleteOne, deleteMany), all run against a collection of documents.

What is the difference between updateOne and updateMany?

updateOne changes only the first document that matches your filter, while updateMany changes every document that matches. Both take a filter and an update, and both should use an operator like $set so you change specific fields instead of accidentally replacing the whole document.

Why should I use $set when updating a document?

$set tells MongoDB to change only the fields you name and leave everything else untouched. Without an update operator, an update can replace the entire document and wipe fields you did not mention. Modern mongosh throws an error to stop this, but making $set a habit keeps your updates safe and predictable.

How is a MongoDB document different from a SQL row?

A SQL row must fit a table's fixed columns, so every row shares the same structure. A MongoDB document is a flexible JSON-like object, so each document in a collection can have its own set of fields and can contain nested objects and arrays directly. This makes MongoDB more flexible, but it also means your application should stay consistent about the shape it writes.

How do I delete all documents in a collection?

Run db.users.deleteMany({}) — an empty filter matches every document, so this removes them all. It cannot be undone, so always run the same filter with find first to confirm exactly what will be deleted before you run the delete.

Do I need to create the database and collection before inserting data?

No. MongoDB creates the database when you first switch to it with use and write data, and it creates the collection automatically the moment you insert your first document. You do not have to define any schema or columns in advance.