MongoDB单聚合查询跨集合获取已关注用户的story数据
MongoDB单聚合查询关注用户的Story实现
现有集合说明
follow集合:存储用户之间的关注关系story集合:存储用户发布的story内容
需求说明
通过单条聚合查询完成全部逻辑,不拆分多次数据库请求,查询当前用户已关注用户发布的story,筛选规则:
deleted_at为nullupdated_at大于等于1638081000owner_id属于当前用户(user1)的关注列表
示例数据结构
db = { "follow": [ { "_id": 1, "start": "user1", "end": "user2", }, { "_id": 2, "start": "user2", "end": "user3", } ], "story": [ { "_id": 1, "owner_id": "user2", "updated_at": 1638090000, "deleted_at": null }, { "_id": 2, "owner_id": "user3", "updated_at": 1638080000, "deleted_at": null } ] }
原有错误写法问题
原有写法无法运行的核心原因:db.follow.find({"start": "user1"})返回的是MongoDB游标,不是被关注用户ID的数组,直接放入$in中无法完成匹配,且这种写法本质是两次独立请求,不符合单聚合查询的要求。
错误写法示例:
db.story.aggregate([ { "$match": { "deleted_at": null, "updated_at": { $gte: 1638081000 }, "owner_id": { $in: [ db.follow.find({"start": "user1"}) ] } } } ])
正确聚合实现
通过$lookup实现跨集合关联校验,所有逻辑在单条聚合管道中完成:
db.story.aggregate([ // 前置过滤基础条件,减少后续关联计算的数据量 { $match: { deleted_at: null, updated_at: { $gte: 1638081000 } } }, // 关联follow集合,校验story发布者是否在当前用户关注列表 { $lookup: { from: "follow", let: { storyOwner: "$owner_id" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: ["$start", "user1"] }, { $eq: ["$end", "$$storyOwner"] } ] } } } ], as: "followRelations" } }, // 过滤掉不存在关注关系的story { $match: { followRelations: { $ne: [] } } }, // 移除关联产生的临时字段,返回标准story结构 { $project: { followRelations: 0 } } ])
查询结果说明
基于示例数据,最终仅返回owner_id为user2的story文档:user1仅关注了user2,user2发布的story时间戳符合筛选要求;user3不是user1的关注对象,且其发布的story时间戳也不满足阈值要求,会被过滤。
内容的提问来源于stack exchange,提问作者SeYeD.Dev
相关产品推荐
相关产品推荐

