MongoDB嵌套聚合(关联查询):获取likeUsers数组中用户完整信息
Populate nested
likeUsers with full user details using MongoDB aggregation Got it, let's walk through how to solve this nested join scenario. You need to pull full user data from your users collection into the likeUsers array nested inside each review in your content documents. Here's a complete aggregation pipeline that does exactly that:
db.content.aggregate([ // Step 1: Unwind the reviews array to work with individual reviews { $unwind: { path: "$reviews", preserveNullAndEmptyArrays: true // Keep docs even if reviews is empty } }, // Step 2: Unwind the likeUsers array inside each review { $unwind: { path: "$reviews.likeUsers", preserveNullAndEmptyArrays: true // Keep reviews even if likeUsers is empty } }, // Step 3: Look up user details from the users collection { $lookup: { from: "users", localField: "reviews.likeUsers._id", foreignField: "_id", as: "reviews.likeUsers" } }, // Step 4: Unwind the lookup result (since $lookup returns an array) { $unwind: { path: "$reviews.likeUsers", preserveNullAndEmptyArrays: true // Handle cases where no user matches } }, // Step 5: Group back likeUsers into an array per review { $group: { _id: { contentId: "$_id", reviewId: "$reviews._id" }, // Preserve all other review fields headline: { $first: "$reviews.headline" }, body: { $first: "$reviews.body" }, dislikeUsers: { $first: "$reviews.dislikeUsers" }, isCritic: { $first: "$reviews.isCritic" }, isSpoilers: { $first: "$reviews.isSpoilers" }, isTop: { $first: "$reviews.isTop" }, rate: { $first: "$reviews.rate" }, userId: { $first: "$reviews.userId" }, date: { $first: "$reviews.date" }, // Aggregate likeUsers back into an array likeUsers: { $push: "$reviews.likeUsers" } } }, // Step 6: Group back reviews into an array per content document { $group: { _id: "$_id.contentId", // Aggregate reviews back into an array reviews: { $push: { _id: "$_id.reviewId", headline: "$headline", body: "$body", likeUsers: "$likeUsers", dislikeUsers: "$dislikeUsers", isCritic: "$isCritic", isSpoilers: "$isSpoilers", isTop: "$isTop", rate: "$rate", userId: "$userId", date: "$date" } } } } ])
Let's break down each step:
- $unwind (reviews): Splits the
reviewsarray into separate documents, so we can process each review individually. ThepreserveNullAndEmptyArraysflag ensures we don't lose content documents that have no reviews. - $unwind (likeUsers): Splits the
likeUsersarray inside each review into single elements. This lets us run the lookup on each user ID individually. - $lookup: Fetches the full user document from the
userscollection that matches the_idinlikeUsers. The result is stored back inreviews.likeUsers(which becomes an array with one element). - $unwind (lookup result): Converts the array from the lookup into a single object (since each likeUser ID should match exactly one user).
- First $group: Reassembles the
likeUsersarray for each review, while preserving all other review fields. We group by both the content ID and review ID to keep each review unique. - Second $group: Reassembles the
reviewsarray back into the original content document structure, so you end up with the same document shape as the input but with populatedlikeUsers.
Notes:
- Replace
db.contentandfrom: "users"with your actual collection names if they're different. - If you have other top-level fields in your content documents (beyond
_idandreviews), add them to the final$groupstage using$firstto preserve them.
内容的提问来源于stack exchange,提问作者Ehsan Farahani Asil
相关产品推荐
相关产品推荐

