MongoDB聚合查询如何跨集合关联获取其他集合数据
MongoDB聚合关联post集合实现方案
你可以直接在原有聚合管道的$project阶段后、$sort阶段前,插入$lookup关联和字段提取逻辑,无需改动原有已实现的统计逻辑,且分组后再做关联的性能远高于在明细阶段关联。
完整修改后的聚合代码
db.Vote.aggregate([ { $match: { surveyId: "e6d38e1ecd", "comment.topic": { $exists: 1 }, } }, { $group: { _id: { topic: "$comment.topic", text_sentiment: "$comment.text_sentiment" }, total: { $sum: 1 }, postIds: { $push: "$postId" } } }, { $group: { _id: "$_id.topic", total: { $sum: "$total" }, text_sentiments: { $push: { k: "$_id.text_sentiment", v: "$total" } }, postIds: { "$push": "$postIds" } } }, { $project: { topic: "$_id", topicOccurance: "$total", sentiment: { "$arrayToObject": "$text_sentiments" }, postIds: { $reduce: { input: "$postIds", initialValue: [], in: { $concatArrays: [ "$$value", "$$this" ] } } } } }, // 新增的关联、字段处理阶段 { $lookup: { from: "post", // 若你的post集合实际名称为posts,修改此处即可 localField: "postIds", foreignField: "_id", as: "matchedPosts" } }, { $project: { topic: 1, topicOccurance: 1, // 补全三类情感默认值,避免无数据时字段缺失 sentiment: { $mergeObjects: [ { positive: 0, negative: 0, neutral: 0 }, "$sentiment" ] }, // 对postId去重 postIds: { $setUnion: ["$postIds", []] }, // 提取关联到的post分类并去重 categories: { $setUnion: ["$matchedPosts.category", []] } } }, // 原有排序逻辑 { $sort: { "topicOccurance": -1 } } ])
关键逻辑说明
$lookup阶段直接用分组后得到的postIds数组关联post集合的_id字段,MongoDB会自动匹配数组中所有id对应的post文档,不需要额外写关联条件- 用
$mergeObjects给情感统计字段补默认值,保证即使某类情感没有对应数据,返回结果里也会存在positive/negative/neutral三个字段,值为0 - 用
$setUnion对postIds和categories做去重处理,避免同一个post、同一个分类因为对应多条同主题评论重复出现在结果数组中 - 关联逻辑放在两次分组之后执行,仅需要对最终返回的主题结果做关联,不需要逐一对每条Vote评论做关联,数据量越大性能优势越明显
- 请保证
Vote.postId和post._id的字段类型一致,若一边是字符串一边是对象ID/数字,会导致关联匹配失败
内容的提问来源于stack exchange,提问作者Suhail Gupta
相关产品推荐
相关产品推荐

