MongoDB Aggregation for Content Platforms: A Practical Guide

Yashraj PatilYashraj Patil
3 min read

MongoDB's aggregation pipeline is a game-changer for filtering and transforming data in a concise, stage-wise manner. Think of it as an assembly line where each stage processes and refines your data before passing it to the next. In this article, I’ll guide you through its usage with a practical example from my full-stack YouTube-style project.

Here, we are working with two data models: User and Subscription. The User model contains all the information related to the user, such as full name, username, email, password, avatar, etc. The Subscription model has two fields, "subscriber" and "channel," both of which are of type User.

Note: A user is also a channel holder

Our goal? To fetch detailed information about a channel, including its subscriber count, subscriptions, and whether a logged-in user is subscribed to it.


Understanding the Stages

1. $match: Filtering by Username

When a user clicks a video, we extract the username from the request parameters. The $match stage filters the User collection to find the specific document matching this username.

{
  $match: { username: username?.toLowerCase() }
}

2. $lookup: Joining with Subscription

The $lookup stage allows us to perform a left outer join between the User model and the Subscription model.

To get the list of subscribers for the channel:

{ 
  $lookup: { 
    from: "subscriptions", 
    localField: "_id", 
    foreignField: "channel", 
    as: "subscribers" 
  } 
}

To fetch channels the user is subscribed to:

{
    $lookup: {
        from: "subscriptions",
        localField: "_id",
        foreignField: "subscriber",
        as: "subscribedTo"
    }
}

💡 Pro Tip: MongoDB converts model names to lowercase and pluralizes them in the database. For instance, Subscription becomes subscriptions.

3. $addFields: Calculating Counts and Subscription Status

The $addFields stage lets us dynamically compute values and add them to the documents:

  • Subscriber Count : Use $size to get the number of users in the subscribers array.

  • Subscribed Channels Count : Apply $size on the subscribedTo array.

  • Is Subscribed : Use $cond to check if the logged-in user’s ID is in the subscribers array.

{
    $addFields: {
        subscribersCount: { $size: "$subscribers" },
        channelSubscribedTo: { $size: "$subscribedTo" },
        isSubscribed: {
            $cond: {
                if: { $in: [req.user?._id, "$subscribers.subscriber"] },
                then: true,
                else: false
            }
        }
    }
}

4. $project: Sending Only Necessary Data

The $project stage ensures we only send relevant fields to the frontend, reducing payload size.

{
    $project: {
        fullname: 1,
        username: 1,
        subscribersCount: 1,
        channelSubscribedTo: 1,
        isSubscribed: 1,
        avatar: 1,
        coverImage: 1
    }
}

With just a few stages, we crafted an insightful response for the frontend, encompassing channel statistics and user-specific data. MongoDB’s aggregation pipeline is a powerful tool to simplify complex data manipulation tasks. By chaining stages like $match, $lookup, $addFields, and $project, you can transform your collections into precise, meaningful outputs tailored for your application.

Ready to power up your database skills? Experiment with other stages like $group and $sort to unlock more potential. 🚀

Dive into aggregation pipelines today!

0
Subscribe to my newsletter

Read articles from Yashraj Patil directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yashraj Patil
Yashraj Patil