MongoDB嵌套$Lookup实现服务分类ID转分类名称
解决MongoDB服务分类ID转名称数组的聚合查询修改方案
针对你的需求——已关联stores与services集合,现在要把services中categories字段的ID数组替换为categories集合对应的名称数组——可以通过两种方式修改聚合查询实现:
方案一:在关联services时同步处理分类名称
直接在关联services的$lookup中嵌入子管道,对每个服务单独处理分类ID转名称:
db.stores.aggregate([ { $lookup: { from: "services", localField: "services", foreignField: "_id", as: "services", pipeline: [ // 关联categories集合,获取分类文档 { $lookup: { from: "categories", localField: "categories", foreignField: "_id", as: "categoryNames" } }, // 替换categories为名称数组,清理临时字段 { $set: { categories: { $map: { input: "$categoryNames", as: "cat", in: "$$cat.name" } }, categoryNames: "$$REMOVE" } } ] } } ])
逻辑说明:
- 外层
$lookup保持原有逻辑,关联stores与services集合,得到门店对应的服务列表。 - 内层
pipeline对每个匹配到的service做两件事:- 用
$lookup根据service的categoriesID数组,从categories集合拉取对应的分类文档,存到临时字段categoryNames。 - 用
$map遍历categoryNames,提取每个分类的name字段,替换原categories字段,再用$$REMOVE删除临时字段。
- 用
方案二:先拉取所有分类,再批量匹配名称
如果服务数量较多,这种方式可以减少多次关联的开销:
db.stores.aggregate([ // 原逻辑:关联stores与services { $lookup: { from: "services", localField: "services", foreignField: "_id", as: "services" } }, // 拉取所有涉及的分类文档到临时字段 { $lookup: { from: "categories", localField: "services.categories", foreignField: "_id", as: "allCategories" } }, // 遍历服务列表,替换categories为名称数组 { $set: { services: { $map: { input: "$services", as: "service", in: { // 保留服务原有所有字段 ..."$$service", // 匹配分类名称 categories: { $map: { input: "$$service.categories", as: "catId", in: { $getField: { field: "name", input: { $first: { $filter: { input: "$allCategories", cond: { $eq: ["$$this._id", "$$catId"] } } } } } } } } } } }, // 删除临时分类字段 allCategories: "$$REMOVE" } } ])
逻辑说明:
- 完成
stores与services的关联后,用$lookup一次性拉取所有服务涉及的分类文档,存到allCategories。 - 用
$map遍历每个服务,保留原有字段的同时,对每个分类ID,从allCategories中过滤匹配的文档并提取name字段,最终形成名称数组替换原categories。 - 最后清理临时的
allCategories字段。
两种方案都能输出你期望的格式,比如某个服务的categories字段会变成:
"categories": [ "cat 1", "cat 2" ]
内容的提问来源于stack exchange,提问作者Mariano L
相关产品推荐
相关产品推荐

