Published on

MongoDB CRUD Operations: Create, Read, Update, Delete

Authors

MongoDB CRUD Operations: Create, Read, Update, Delete

Welcome to Part 3 of our MongoDB Zero to Hero series. After understanding the fundamentals and setting up MongoDB, it's time to dive into the core operations that make MongoDB powerful.

What Are CRUD Operations?

CRUD operations are the four basic functions of persistent storage:

  • Create - Insert new documents
  • Read - Query and retrieve documents
  • Update - Modify existing documents
  • Delete - Remove documents

MongoDB provides powerful and flexible methods for each of these operations.

Setting Up Our Practice Database

Let's create a sample database for our examples:

// Switch to a new database
use blogDB

// Create a collection with some sample data
db.users.insertMany([
  {
    name: "Alice Johnson",
    email: "alice@example.com",
    age: 28,
    city: "New York",
    hobbies: ["reading", "photography", "hiking"],
    active: true,
    joinDate: new Date("2023-01-15")
  },
  {
    name: "Bob Smith",
    email: "bob@example.com",
    age: 34,
    city: "San Francisco",
    hobbies: ["gaming", "cooking"],
    active: true,
    joinDate: new Date("2023-03-20")
  },
  {
    name: "Carol Davis",
    email: "carol@example.com",
    age: 25,
    city: "Chicago",
    hobbies: ["music", "dancing", "travel"],
    active: false,
    joinDate: new Date("2023-02-10")
  }
])

Create Operations

insertOne()

Insert a single document:

db.users.insertOne({
    name: 'David Wilson',
    email: 'david@example.com',
    age: 31,
    city: 'Austin',
    hobbies: ['cycling', 'coding'],
    active: true,
    joinDate: new Date(),
});

insertMany()

Insert multiple documents:

db.users.insertMany([
    {
        name: 'Emma Brown',
        email: 'emma@example.com',
        age: 29,
        city: 'Seattle',
        hobbies: ['yoga', 'painting'],
        active: true,
        joinDate: new Date(),
    },
    {
        name: 'Frank Miller',
        email: 'frank@example.com',
        age: 40,
        city: 'Denver',
        hobbies: ['skiing', 'photography'],
        active: true,
        joinDate: new Date(),
    },
]);

Insert Options

// Insert with custom _id
db.users.insertOne({
    _id: 'custom_id_123',
    name: 'Grace Lee',
    email: 'grace@example.com',
    age: 27,
});

// Insert with ordered option (stops on first error)
db.users.insertMany(
    [
        { name: 'User 1', email: 'user1@example.com' },
        { name: 'User 2', email: 'user2@example.com' },
    ],
    { ordered: false },
);

Read Operations

find()

Basic queries:

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

// Find with pretty formatting
db.users.find().pretty();

// Find specific documents
db.users.find({ city: 'New York' });

// Find with multiple conditions
db.users.find({
    city: 'New York',
    active: true,
});

findOne()

Find a single document:

// Find first matching document
db.users.findOne({ city: 'San Francisco' });

// Find by _id
db.users.findOne({ _id: ObjectId('...') });

Query Operators

Comparison Operators

// Greater than
db.users.find({ age: { $gt: 30 } });

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

// Less than
db.users.find({ age: { $lt: 30 } });

// Less than or equal
db.users.find({ age: { $lte: 30 } });

// Not equal
db.users.find({ city: { $ne: 'New York' } });

// In array
db.users.find({ city: { $in: ['New York', 'Chicago'] } });

// Not in array
db.users.find({ city: { $nin: ['New York', 'Chicago'] } });

Logical Operators

// AND (implicit)
db.users.find({
    age: { $gte: 25 },
    city: 'New York',
});

// AND (explicit)
db.users.find({
    $and: [{ age: { $gte: 25 } }, { city: 'New York' }],
});

// OR
db.users.find({
    $or: [{ city: 'New York' }, { city: 'Chicago' }],
});

// NOT
db.users.find({
    age: { $not: { $lt: 30 } },
});

// NOR
db.users.find({
    $nor: [{ city: 'New York' }, { age: { $lt: 25 } }],
});

Array Operators

// Find documents with specific array element
db.users.find({ hobbies: 'reading' });

// Find documents with all specified elements
db.users.find({ hobbies: { $all: ['reading', 'photography'] } });

// Find documents with array of specific size
db.users.find({ hobbies: { $size: 2 } });

// Find using $elemMatch
db.users.find({
    hobbies: {
        $elemMatch: { $in: ['reading', 'gaming'] },
    },
});

Element Operators

// Check if field exists
db.users.find({ email: { $exists: true } });

// Check field type
db.users.find({ age: { $type: 'number' } });

Projection

Control which fields to return:

// Include specific fields
db.users.find({}, { name: 1, email: 1 });

// Exclude specific fields
db.users.find({}, { hobbies: 0, joinDate: 0 });

// Include fields except _id
db.users.find({}, { name: 1, email: 1, _id: 0 });

Sorting and Limiting

// Sort ascending
db.users.find().sort({ age: 1 });

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

// Sort by multiple fields
db.users.find().sort({ city: 1, age: -1 });

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

// Skip results (pagination)
db.users.find().skip(2).limit(3);

// Combine operations
db.users.find({ active: true }).sort({ age: -1 }).limit(5).pretty();

Update Operations

updateOne()

Update a single document:

// Update with $set
db.users.updateOne({ name: 'Alice Johnson' }, { $set: { age: 29, city: 'Boston' } });

// Add to array with $push
db.users.updateOne({ name: 'Alice Johnson' }, { $push: { hobbies: 'swimming' } });

// Add multiple items to array
db.users.updateOne({ name: 'Bob Smith' }, { $push: { hobbies: { $each: ['tennis', 'golf'] } } });

updateMany()

Update multiple documents:

// Update all inactive users
db.users.updateMany({ active: false }, { $set: { status: 'inactive', lastUpdated: new Date() } });

// Increment age for all users in specific city
db.users.updateMany({ city: 'New York' }, { $inc: { age: 1 } });

replaceOne()

Replace entire document:

db.users.replaceOne(
    { name: 'Carol Davis' },
    {
        name: 'Carol Davis',
        email: 'carol.davis@newcompany.com',
        age: 26,
        city: 'Miami',
        hobbies: ['surfing', 'yoga'],
        active: true,
        joinDate: new Date('2023-02-10'),
        updatedDate: new Date(),
    },
);

Update Operators

Field Update Operators

// Set field value
db.users.updateOne({ name: 'David Wilson' }, { $set: { city: 'Portland', lastLogin: new Date() } });

// Remove field
db.users.updateOne({ name: 'David Wilson' }, { $unset: { lastLogin: '' } });

// Increment numeric field
db.users.updateOne({ name: 'Alice Johnson' }, { $inc: { age: 1, loginCount: 1 } });

// Multiply numeric field
db.users.updateOne({ name: 'Bob Smith' }, { $mul: { age: 1.1 } });

// Rename field
db.users.updateOne({ name: 'Emma Brown' }, { $rename: { age: 'yearsOld' } });

// Set only if field doesn't exist
db.users.updateOne(
    { name: 'Frank Miller' },
    { $setOnInsert: { createdDate: new Date() } },
    { upsert: true },
);

Array Update Operators

// Add to array (if not exists)
db.users.updateOne({ name: 'Alice Johnson' }, { $addToSet: { hobbies: 'running' } });

// Remove from array
db.users.updateOne({ name: 'Bob Smith' }, { $pull: { hobbies: 'gaming' } });

// Remove multiple items from array
db.users.updateOne({ name: 'Carol Davis' }, { $pullAll: { hobbies: ['music', 'dancing'] } });

// Remove first or last array element
db.users.updateOne(
    { name: 'David Wilson' },
    { $pop: { hobbies: 1 } }, // 1 for last, -1 for first
);

// Update array element by position
db.users.updateOne({ name: 'Emma Brown' }, { $set: { 'hobbies.0': 'meditation' } });

// Update array element by condition
db.users.updateOne(
    { name: 'Frank Miller', hobbies: 'photography' },
    { $set: { 'hobbies.$': 'landscape photography' } },
);

Upsert Option

// Insert if document doesn't exist, update if it does
db.users.updateOne(
    { email: 'new@example.com' },
    {
        $set: {
            name: 'New User',
            city: 'Unknown',
            active: true,
            joinDate: new Date(),
        },
    },
    { upsert: true },
);

Delete Operations

deleteOne()

Delete a single document:

// Delete first matching document
db.users.deleteOne({ name: 'Carol Davis' });

// Delete by _id
db.users.deleteOne({ _id: ObjectId('...') });

deleteMany()

Delete multiple documents:

// Delete all inactive users
db.users.deleteMany({ active: false });

// Delete users older than 35
db.users.deleteMany({ age: { $gt: 35 } });

// Delete users from specific cities
db.users.deleteMany({
    city: { $in: ['Chicago', 'Denver'] },
});

findOneAndDelete()

Find and delete in one operation:

// Find and delete, returning the deleted document
const deletedUser = db.users.findOneAndDelete({
    city: 'Austin',
});

Advanced CRUD Patterns

Bulk Operations

// Bulk write operations
db.users.bulkWrite([
    {
        insertOne: {
            document: {
                name: 'Bulk User 1',
                email: 'bulk1@example.com',
                age: 25,
            },
        },
    },
    {
        updateOne: {
            filter: { name: 'Alice Johnson' },
            update: { $set: { lastActive: new Date() } },
        },
    },
    {
        deleteOne: {
            filter: { name: 'Frank Miller' },
        },
    },
]);

findOneAndUpdate()

// Find, update, and return the document
const updatedUser = db.users.findOneAndUpdate(
    { name: 'Bob Smith' },
    { $set: { city: 'Los Angeles' } },
    { returnDocument: 'after' }, // Return updated document
);

findOneAndReplace()

// Find, replace, and return the document
const replacedUser = db.users.findOneAndReplace(
    { name: 'Emma Brown' },
    {
        name: 'Emma Brown-Wilson',
        email: 'emma.wilson@example.com',
        age: 30,
        city: 'Portland',
        active: true,
    },
    { returnDocument: 'after' },
);

Error Handling and Best Practices

Write Concern

// Ensure write is acknowledged
db.users.insertOne(
    { name: 'Important User', email: 'important@example.com' },
    { writeConcern: { w: 'majority', j: true } },
);

Read Concern

// Read with specific read concern
db.users.find({ active: true }).readConcern('majority');

Validation

// Create collection with validation
db.createCollection('validatedUsers', {
    validator: {
        $jsonSchema: {
            bsonType: 'object',
            required: ['name', 'email', 'age'],
            properties: {
                name: {
                    bsonType: 'string',
                    description: 'must be a string and is required',
                },
                email: {
                    bsonType: 'string',
                    pattern: '^.+@.+$',
                    description: 'must be a valid email address',
                },
                age: {
                    bsonType: 'int',
                    minimum: 0,
                    maximum: 120,
                    description: 'must be an integer between 0 and 120',
                },
            },
        },
    },
});

Performance Tips

  1. Use Indexes: Create indexes on frequently queried fields
  2. Limit Results: Use limit() to prevent large result sets
  3. Project Fields: Only return needed fields with projection
  4. Batch Operations: Use bulk operations for multiple writes
  5. Avoid Large Skips: Use alternative pagination methods

Common Pitfalls to Avoid

  1. Case Sensitivity: MongoDB queries are case-sensitive
  2. Array Indexing: Remember arrays are 0-indexed
  3. Data Types: Be consistent with data types
  4. Large Documents: Keep document size reasonable (16MB limit)
  5. Update Operators: Don't mix update operators incorrectly

What's Next?

Now that you've mastered CRUD operations, you're ready to explore MongoDB Data Modeling to learn how to structure your data effectively, or dive into Indexing and Performance to optimize your queries.

Series Navigation


This is Part 3 of the MongoDB Zero to Hero series. Each part builds upon the previous ones, so make sure you're comfortable with the fundamentals before moving on to more advanced topics.

Enjoyed this post?

Subscribe to get notified about new posts and updates. No spam, unsubscribe anytime.

By subscribing, you agree to our Privacy Policy. You can unsubscribe at any time.

Discussion (0)

This website is still under development. If you encounter any issues, please contact me