Skip to content

CRUD Operations

πŸ“– MongoDB CRUD Operations - Complete CRUD documentation πŸ“– Query and Projection Operators - Operator reference

Insert Operations

insertOne()

πŸ“– insertOne() - Insert one document

// Basic insert
db.users.insertOne({
  name: "Alice",
  email: "alice@example.com",
  age: 30,
  tags: ["admin", "user"],
  address: {
    city: "Seattle",
    state: "WA"
  },
  createdAt: new Date()
});

// Returns: { acknowledged: true, insertedId: ObjectId("...") }

Key Points: - _id is auto-generated as ObjectId if not provided - Custom _id is allowed (any type, must be unique) - Document must not exceed 16 MB - Throws error if _id already exists (duplicate key error)

insertMany()

πŸ“– insertMany() - Insert multiple documents

db.users.insertMany([
  { name: "Bob", email: "bob@example.com", age: 25 },
  { name: "Charlie", email: "charlie@example.com", age: 35 }
], { ordered: false });

// Returns: { acknowledged: true, insertedIds: { '0': ObjectId("..."), '1': ObjectId("...") } }

Ordered vs Unordered: - ordered: true (default) - Stops on first error, guarantees order - ordered: false - Continues on errors, may execute in any order, faster for large batches - Unordered inserts are preferred for bulk data loading

Find Operations

find() and findOne()

πŸ“– find() - Query documents

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

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

// Find with projection
db.users.find(
  { status: "active" },
  { name: 1, email: 1, _id: 0 }  // Include name, email; exclude _id
);

// findOne returns first match
db.users.findOne({ email: "alice@example.com" });

Comparison Operators

// Equal (implicit)
db.users.find({ age: 25 });
// Explicit: { age: { $eq: 25 } }

// Not equal
db.users.find({ status: { $ne: "inactive" } });

// Greater than / Greater than or equal
db.users.find({ age: { $gt: 18 } });
db.users.find({ age: { $gte: 21 } });

// Less than / Less than or equal
db.users.find({ price: { $lt: 100 } });
db.users.find({ price: { $lte: 50 } });

// In / Not in
db.users.find({ status: { $in: ["active", "pending"] } });
db.users.find({ role: { $nin: ["admin"] } });

// Range (combining operators)
db.users.find({ age: { $gte: 18, $lte: 65 } });

Logical Operators

// AND (implicit - multiple conditions)
db.users.find({ status: "active", age: { $gt: 18 } });

// AND (explicit)
db.users.find({ $and: [{ status: "active" }, { age: { $gt: 18 } }] });

// OR
db.users.find({ $or: [{ status: "active" }, { role: "admin" }] });

// NOT
db.users.find({ age: { $not: { $gt: 65 } } });

// NOR (none of the conditions)
db.users.find({ $nor: [{ status: "inactive" }, { age: { $lt: 18 } }] });

When to use explicit $and: - When you need multiple conditions on the same field - { $and: [{ price: { $gt: 10 } }, { price: { $lt: 50 } }] } - Same as: { price: { $gt: 10, $lt: 50 } }

Element Operators

// Field exists
db.users.find({ email: { $exists: true } });
db.users.find({ middleName: { $exists: false } });

// Field type
db.users.find({ age: { $type: "number" } });
db.users.find({ age: { $type: "string" } });  // Find mistyped ages

Array Operators

// Match array containing value
db.users.find({ tags: "admin" });

// Match array containing all values
db.users.find({ tags: { $all: ["admin", "user"] } });

// Match array with exact size
db.users.find({ tags: { $size: 3 } });

// Element match - conditions on SAME element
db.scores.find({
  results: { $elemMatch: { $gte: 80, $lt: 90 } }
});
// vs dot notation - conditions can match DIFFERENT elements
db.scores.find({ "results": { $gte: 80, $lt: 90 } });

Evaluation Operators

// Regular expression
db.users.find({ name: { $regex: /^Ali/i } });
db.users.find({ name: { $regex: "^Ali", $options: "i" } });

// Text search (requires text index)
db.articles.find({ $text: { $search: "coffee shop" } });

// Expression (use aggregation expressions in find)
db.inventory.find({ $expr: { $gt: ["$qty", "$reorder"] } });

Projections

// Include specific fields (inclusion projection)
db.users.find({}, { name: 1, email: 1 });
// Returns: { _id: ObjectId("..."), name: "Alice", email: "alice@..." }

// Exclude specific fields (exclusion projection)
db.users.find({}, { password: 0, ssn: 0 });

// Cannot mix inclusion and exclusion (except _id)
db.users.find({}, { name: 1, _id: 0 });  // Valid - _id exclusion is special

// Array projection operators
db.posts.find({}, { comments: { $slice: 5 } });         // First 5
db.posts.find({}, { comments: { $slice: -3 } });        // Last 3
db.posts.find({}, { comments: { $slice: [10, 5] } });   // Skip 10, take 5
db.posts.find({}, { "comments.$": 1 });                  // First matching element
db.posts.find({}, { comments: { $elemMatch: { author: "Alice" } } }); // Matching element

Cursor Methods

// Sort (1 = ascending, -1 = descending)
db.users.find().sort({ age: -1, name: 1 });

// Limit results
db.users.find().limit(10);

// Skip results (pagination)
db.users.find().skip(20).limit(10);  // Page 3 with 10 per page

// Count
db.users.find({ status: "active" }).count();
db.users.countDocuments({ status: "active" });  // Preferred

// Execution order: sort -> skip -> limit (regardless of method call order)

Update Operations

updateOne() and updateMany()

πŸ“– Update Operations - Update documentation

// Update one document
db.users.updateOne(
  { email: "alice@example.com" },
  { $set: { lastLogin: new Date() }, $inc: { loginCount: 1 } }
);

// Update many documents
db.users.updateMany(
  { status: "inactive" },
  { $set: { archived: true, archivedAt: new Date() } }
);

// Returns: { acknowledged: true, matchedCount: 1, modifiedCount: 1 }

Update Operators

πŸ“– Update Operators - Complete operator reference

Field Update Operators:

// $set - Set field value (create if not exists)
{ $set: { name: "New Name", "address.city": "Portland" } }

// $unset - Remove field
{ $unset: { temporaryField: "" } }

// $inc - Increment (positive or negative)
{ $inc: { quantity: -1, totalSold: 1 } }

// $mul - Multiply
{ $mul: { price: 1.1 } }  // 10% price increase

// $rename - Rename field
{ $rename: { "old_name": "new_name" } }

// $min - Update only if new value is less than current
{ $min: { lowScore: 50 } }

// $max - Update only if new value is greater than current
{ $max: { highScore: 99 } }

// $currentDate - Set to current date
{ $currentDate: { lastModified: true } }
{ $currentDate: { lastModified: { $type: "timestamp" } } }

Array Update Operators:

// $push - Add element to array
{ $push: { tags: "newTag" } }

// $push with modifiers
{ $push: { scores: { $each: [90, 85, 95], $sort: -1, $slice: 10 } } }
// Adds all scores, sorts descending, keeps top 10

// $addToSet - Add only if not already present
{ $addToSet: { tags: "unique" } }
{ $addToSet: { tags: { $each: ["a", "b", "c"] } } }

// $pull - Remove matching elements
{ $pull: { tags: "oldTag" } }
{ $pull: { scores: { $lt: 60 } } }  // Remove all scores below 60

// $pop - Remove first (-1) or last (1) element
{ $pop: { queue: -1 } }  // Remove first
{ $pop: { queue: 1 } }   // Remove last

// $ positional operator - Update matched array element
db.collection.updateOne(
  { "items.productId": "P123" },
  { $set: { "items.$.quantity": 5 } }
);

// $[] all positional - Update all array elements
{ $inc: { "scores.$[]": 10 } }  // Add 10 to all scores

// $[<identifier>] filtered positional
db.collection.updateOne(
  { _id: 1 },
  { $set: { "grades.$[elem].score": 100 } },
  { arrayFilters: [{ "elem.score": { $lt: 60 } }] }
);

replaceOne()

db.users.replaceOne(
  { email: "alice@example.com" },
  { name: "Alice Smith", email: "alice@example.com", age: 31, status: "active" }
);
- Replaces the entire document (except _id) - Cannot use update operators ($set, $inc, etc.) - Useful for full document replacement

findOneAndUpdate() / findOneAndReplace() / findOneAndDelete()

// Returns the document before or after modification
const result = db.users.findOneAndUpdate(
  { email: "alice@example.com" },
  { $inc: { loginCount: 1 } },
  { returnDocument: "after", upsert: true }
);

// findOneAndDelete - atomically find and remove
const deleted = db.sessions.findOneAndDelete(
  { sessionId: "abc123" }
);

Options: - returnDocument: "before" (default) or "after" - Return pre or post modification - upsert: true - Insert if no match - sort: { field: 1 } - Which document to modify if multiple match - projection: { field: 1 } - Fields to return

Delete Operations

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

// Delete many
db.users.deleteMany({ status: "inactive", lastLogin: { $lt: new Date("2023-01-01") } });

// Delete all documents (empty filter)
db.logs.deleteMany({});

// Returns: { acknowledged: true, deletedCount: 5 }

Bulk Write Operations

πŸ“– bulkWrite() - Bulk operations documentation

db.collection.bulkWrite([
  {
    insertOne: {
      document: { name: "New Item", quantity: 10 }
    }
  },
  {
    updateOne: {
      filter: { name: "Existing Item" },
      update: { $inc: { quantity: 5 } }
    }
  },
  {
    updateMany: {
      filter: { status: "pending" },
      update: { $set: { status: "processed" } }
    }
  },
  {
    replaceOne: {
      filter: { name: "Old Item" },
      replacement: { name: "Old Item", quantity: 0, archived: true }
    }
  },
  {
    deleteOne: {
      filter: { name: "Deleted Item" }
    }
  },
  {
    deleteMany: {
      filter: { quantity: 0, archived: true }
    }
  }
], { ordered: false });

Return Value:

{
  acknowledged: true,
  insertedCount: 1,
  matchedCount: 5,
  modifiedCount: 4,
  deletedCount: 2,
  upsertedCount: 0,
  insertedIds: { '0': ObjectId("...") },
  upsertedIds: {}
}

Write Concerns and Read Concerns

Write Concern

db.users.insertOne(
  { name: "Alice" },
  { writeConcern: { w: "majority", j: true, wtimeout: 5000 } }
);
Setting Description
w: 1 Acknowledge from primary only (default)
w: "majority" Acknowledge from majority of replica set
w: 0 No acknowledgment (fire and forget)
j: true Wait for journal write
wtimeout Timeout in milliseconds

Read Concern

Level Description
local Most recent data from primary (default)
available Most recent data (may return orphaned docs on sharded clusters)
majority Data acknowledged by majority
linearizable Reflects all successful majority-acknowledged writes
snapshot Data from a specific point in time (transactions)