MongoDB聚合查询:如何匹配数组交集的员工文档
解决MongoDB $lookup中匹配数组交集的员工文档问题
我来帮你搞定这个$lookup的匹配难题!你的核心需求是关联员工集合时,只保留那些自身services数组和主集合传递的$$services数组存在交集的员工文档对吧?
问题分析
你当前的代码先做了$project生成交集体,但这一步应该放在过滤之后——我们需要先筛选出符合条件的员工,再按需处理字段结构,不然会丢失原始文档的匹配判断依据。
修正后的$lookup配置
调整员工集合的lookup pipeline,先通过$match过滤出有交集的文档,再按需投影字段:
{ $lookup: { from: collection_names.EMPLOYEE, let: { services: "$services._id" }, pipeline: [ { $match: { $expr: { // 判断两个services数组的交集长度大于0,即存在匹配元素 $gt: [ { $size: { $setIntersection: ["$services", "$$services"] } }, 0 ] } } }, // 这里可以添加$project来指定你需要保留的员工字段,比如: // { $project: { name: 1, services: 1, _id: 1 } } ], as: "employees" } }
完整的聚合代码
把修正后的lookup替换到你的完整聚合链中,最终代码如下:
collection.aggregate([ { $geoNear: { near: { type: "Point", coordinates: correct_format_loc }, key: 'location', distanceField: 'location.dist', maxDistance: range * 1000, // 1000 meters query: { name: re }, spherical: true, } }, { $lookup: { from: collection_names.SERVICE, let: { business: "$_id" }, pipeline: [ { $match: { $expr: { $eq: ["$business", "$$business"] } } }, { $project: { _id: 1, name: 1, price: 1, category: 1, duration: 1 } } ], as: "services" } }, { $lookup: { from: collection_names.EMPLOYEE, let: { services: "$services._id" }, pipeline: [ { $match: { $expr: { $gt: [ { $size: { $setIntersection: ["$services", "$$services"] } }, 0 ] } } } // 可根据需求添加$project字段 ], as: "employees" } }, { $project: { name: "$name", address: "$address", location: "$location", contact: "$contact", description: "$description", image_paths: "$image_paths", services: '$services', employees: '$employees', rating_avg: { $avg: "$services.rating" } } }, ]).toArray()
关键说明
$setIntersection会返回两个数组的交集元素,用$size获取交集长度,判断长度大于0就说明存在匹配的服务ID- 如果不需要员工的所有字段,在
$match之后添加$project来指定需要的字段即可,比如只保留姓名和服务列表 - 这个逻辑确保只有和当前业务有共同服务的员工才会被关联到结果中
内容的提问来源于stack exchange,提问作者Andrew Serra
相关产品推荐
相关产品推荐

