MongoDB Aggregation for User Channel Profiles

Online platforms like YouTube or Twitch( OR TAKE ANY SOCIAL MEDIA PLATFORM ) understanding user engagement with channels is crucial. Users and channel owners alike benefit from insights such as subscriber counts, channels subscribed to, and subscription status. MongoDB’s aggregation framework offers a powerful solution to derive these insights efficiently. In this blog, we’ll explore how to use MongoDB aggregation to create detailed user channel profiles, enhancing user experience and community engagement.

Understanding the Problem: Imagine a scenario where users can create channels, and they want to know who’s subscribed to their channel and which channels they’re subscribed to. Users visiting these channels also want to see if they’re already subscribed and explore other channels. To provide this information, we need a way to process and aggregate data effectively.

Solution Overview: We’ll leverage MongoDB’s aggregation framework, which allows us to perform complex data processing operations in stages. By constructing an aggregation pipeline, we can extract valuable insights from our data model efficiently.

Reference:youtube.com/watch?v=fDTf1mk-jQg&ab_chan..

Steps:

Data Modeling:

  • Define schemas for users, channels, and subscriptions.

  • Establish relationships between users and channels through subscriptions.

Aggregation Pipeline:

  • Match the user channel by username.

  • Look up subscribers and channels subscribed to.

  • Calculate subscriber counts and channels subscribed to counts.

  • Determine subscription status for the requesting user.

Error Handling:

  • Validate user input to ensure a smooth user experience.

  • Handle cases where the requested channel does not exist.

Response Formatting:

  • Construct a JSON response containing relevant user channel information.

  • Include status codes and appropriate messages for clear communication.

const getUserChannelProfile = asyncHandler(async (req, res) => {
  const { username } = req.params;
  if (!username?.trim()) {
    throw new ApiError(400, "Username Is Missing");
  }
const channel = await User.aggregate([
    {
      $match: {
        username: username?.toLowerCase(),
      },
    },
    {
      $lookup: {
        from: "subscriptions",
        localField: "_id",
        foreignField: "channel",
        as: "subscribers",
      },
    },
    {
      $lookup: {
        from: "subscriptions",
        localField: "_id",
        foreignField: "subscriber",
        as: "subscribedTo",
      },
    },
    {
      $addFields: {
        subscribersCount: { $size: "$subscribers" },
        subscribedCount: { $size: "$subscribedTo" },
        isSubscribed: {
          $cond: {
            if: { $in: [req.user?._id, "$subscribers.subscriber"] },
            then: true,
            else: false,
          },
        },
      },
    },
    {
      $project: {
        fullname: 1,
        username: 1,
        subscribersCount: 1,
        subscribedCount: 1,
        isSubscribed: 1,
        avatar: 1,
        coverImage: 1,
        email: 1,
      },
    },
  ]);
  if (!channel?.length) {
    throw new ApiError(404, "Channel does not exist");
  }
  return res.status(200).json(new ApiResponse(200, channel[0], "User channel fetched successfully"));
});