DEV Community

Cover image for Essential MongoDB: A Practical Guide to Creating CRUD Operations and Powerful Aggregations
Mikael Santilio
Mikael Santilio

Posted on

Essential MongoDB: A Practical Guide to Creating CRUD Operations and Powerful Aggregations

Introduction

MongoDB is a popular NoSQL database, widely used for its flexibility and capacity to handle large volumes of data. In this article, we will explore four crucial operations in MongoDB: insert, find, update, and delete. We will also discuss the stages of an aggregate pipeline that offer powerful functionalities for data analysis and transformation.

MongoDB CRUD Operations

Create/Insert

To insert documents into a MongoDB collection, we use the command insertOne() to add a single document or insertMany() to add multiple documents.

insertOne:

db.collection('users').insertOne({
    name: "John Doe",
    age: 30,
    email: "john.doe@email.com"
});
Enter fullscreen mode Exit fullscreen mode

insertMany:

db.collection('users').insertMany([
    { name: "Ana Doe", age: 25, email: "ana.doe@email.com" },
    { name: "Carlos Mendes", age: 40, email: "carlos.mendes@email.com" }
]);
Enter fullscreen mode Exit fullscreen mode

Read

To read documents, we use the command find(). The first argument is the filter, and the second argument is optional, allowing us to specify which fields will be returned in the query.

find:

db.collection('users').find({ name: "John Doe" }, { name: 1, email: 1 });
Enter fullscreen mode Exit fullscreen mode

Update

Update operations are performed using the methods updateOne() and updateMany(). You can also use operators like $set, $inc and $rename, among others.

updateOne:

db.collection('users').updateOne(
    { email: "john.doe@email.com" },
    { $set: { age: 31 } }
);
Enter fullscreen mode Exit fullscreen mode

updateMany:

const result = db.collection('users').updateMany(
    { age: { $gte: 30 } },
    { $inc: { age: 1 } }
);
Enter fullscreen mode Exit fullscreen mode

Delete

To remove documents, we use the methods deleteOne() and deleteMany().

deleteOne:

db.collection('users').deleteOne({ email: "ana.doe@email.com" });
Enter fullscreen mode Exit fullscreen mode

deleteMany:

db.collection('users').deleteMany({ age: { $lt: 18 } });
Enter fullscreen mode Exit fullscreen mode

Aggregate Pipeline

MongoDB offers an aggregation framework to perform more complex queries that can involve multiple stages linked in a pipeline. Here are some commonly used stages:

1. $match

Filters documents based on specified criteria.

db.collection('sales').aggregate([
    { $match: { status: "finished" } }
]);
Enter fullscreen mode Exit fullscreen mode

2. $group

Groups documents based on a specific key, which can be a value of a field or a combination of fields. Operations performed inside a $group are called accumulators, some of which include $sum, $addToSet, and $first.

db.collection('sales').aggregate([
    {
        $group: {
            _id: "$category",
            totalSales: { $sum: "$value" },
            sales: { $addToSet: '$$ROOT' }
        }
    }
]);
Enter fullscreen mode Exit fullscreen mode

3. $project

Controls which fields are returned. In this stage, you choose which fields will appear and can add new columns with custom values, such as through multiplication. It is important to note that in this stage, you cannot have both projection 0 and 1 for the same field, except for the _id.

db.collection('sales').aggregate([
    {
        $project: {
            _id: 0,
            category: 1,
            priceWithTax: { $multiply: ["$price", 1.2] }
        }
    }
]);
Enter fullscreen mode Exit fullscreen mode

4. $addFields

With this stage, you can add new fields or modify existing fields.

db.collection('sales').aggregate([
    {
        $addFields: {
            priceWithTax: { $multiply: ["$price", 1.2] }
        }
    }
]);
Enter fullscreen mode Exit fullscreen mode

5. $sort

Orders documents in ascending (1) or descending (-1) order.

db.collection('sales').aggregate([
    { $sort: { price: -1 } }
]);
Enter fullscreen mode Exit fullscreen mode

6. $limit and $skip

Control the pagination of results.

db.collection('sales').aggregate([
    { $sort: { price: -1 } },
    { $limit: 10 },
    { $skip: 20 }
]);
Enter fullscreen mode Exit fullscreen mode

7. $unwind

The $unwind operator decomposes an array field into individual documents, generating one document for each element in the array. For example, if your collection has 5 documents, and each document has an array field with 5 objects, the result will be 25 documents. Example in MongoDB Playground

db.collection('sales').aggregate([
   {
        "$unwind": {
            "path": "$products",
            "preserveNullAndEmptyArrays": true
        }
    }
]);
Enter fullscreen mode Exit fullscreen mode

8. $switch

Allows returning results based on conditional evaluations.

db.collection('sales').aggregate([
   {
        "$project": {
            "price_description": {
                $switch: {
                    branches: [
                        { case: { $gt: ["$price", 5] }, then: "greater than 5" },
                        { case: { $lt: ["$price", 5] }, then: "less than 5" },
                    ],
                    default: "unknown price"
                }
            }
        }
    }
]);
Enter fullscreen mode Exit fullscreen mode

9. $map, $filter e $reduce

These are array manipulation operations, generally used inside $project or $addFields. Example in MongoDB Playground

db.collection('sales').aggregate([
  {
    "$project": {
      products: {
        "$map": {
          "input": "$products",
          "as": "product",
          "in": {
            "$concat": [
              "$$product.name",
              " - ",
              {
                "$toString": "$$product.price"
              }
            ]
          }
        }
      },
      products_w_price_gte_10: {
        "$filter": {
          "input": "$products",
          "as": "product",
          "cond": {
            "$gte": [
              "$$product.price",
              10
            ]
          }
        }
      },
      products_values: {
        "$reduce": {
          "input": "$products.price",
          "initialValue": "",
          "in": {
            "$concat": [
              "$$value",
              {
                "$cond": [
                  {
                    "$eq": [
                      "$$value",
                      ""
                    ]
                  },
                  "",
                  ", "
                ]
              },
              {
                "$toString": "$$this"
              }
            ]
          }
        }
      }
    }
  }
]);
Enter fullscreen mode Exit fullscreen mode

10. $lookup

The $lookup stage is used to search records in another collection based on a foreign key, similar to a JOIN in SQL. It can be used in a simple way by comparing two keys (localField and foreignField):

db.collection('sales').aggregate([
    {
        "$lookup": {
            "from": "users",
            "localField": "user_id",
            "foreignField": "_id",
            "as": "users"
        }
    }
]);
Enter fullscreen mode Exit fullscreen mode

The $lookup can also use additional comparison fields by utilizing let for variables and a specific pipeline. It is important to remember that if you use a pipeline inside a lookup, it is only possible to compare variables defined in let with the columns of the collection chosen using $expr. Example in MongoDB Playground

db.collection('sales').aggregate([
    {
        "$lookup": {
            "from": "users",
            "let": { "userId": "$user_id" },
            "pipeline": [
                {
                    "$match": {
                        "$expr": {
                            "$and": [
                                { "$eq": ["$user_id", "$$userId"] }
                            ]
                        }
                    }
                },
                {
                    "$project": {
                        "_id": 0,
                        "email": 1
                    }
                },
                {
                    "$limit": 1
                }
            ],
            "as": "users"
        }
    }
]);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)