MongoDB聚合:从分类树提取所有层级并合并至其他集合
生成完整分类层级的MongoDB聚合方案
以下是实现需求的完整聚合管道,能自动生成所有父分类层级,即使没有对应产品:
完整聚合管道
db.products.aggregate([ // 1. 收集所有不重复的产品分类字符串 { $group: { _id: null, uniqueCategoryPaths: { $addToSet: "$category" } } }, // 2. 展开每个唯一分类路径 { $unwind: "$uniqueCategoryPaths" }, // 3. 将分类路径字符串转换为干净的分类数组(去除空字符串) { $project: { categoryArray: { $filter: { input: { $split: ["$uniqueCategoryPaths", ">"] }, as: "cat", cond: { $ne: ["$$cat", ""] } } } } }, // 4. 生成该分类的所有前缀层级数组(如['tech','tv','4k']生成[['tech'], ['tech','tv'], ['tech','tv','4k']]) { $project: { allLevelArrays: { $map: { input: { $range: [1, { $add: [{ $size: "$categoryArray" }, 1] }] }, as: "idx", in: { $slice: ["$categoryArray", "$$idx"] } } } } }, // 5. 展开所有层级数组 { $unwind: "$allLevelArrays" }, // 6. 将层级数组转换回带>包裹的完整路径字符串 { $project: { fullCategoryPath: { $concat: [ ">", { $join: ["$allLevelArrays", ">"] }, ">" ] } } }, // 7. 去重,避免重复的分类层级 { $group: { _id: "$fullCategoryPath" } }, // 8. 将结果合并到目标分类集合 { $merge: { into: "category_hierarchy", // 替换为你的目标集合名 on: "_id", whenMatched: "keepExisting", // 已存在则保留原数据 whenNotMatched: "insert" // 不存在则插入 } } ])
关键步骤解释
- 步骤3:通过
$split按>拆分字符串,再用$filter移除拆分后产生的空字符串(因为原路径首尾都是>),得到干净的分类数组。 - 步骤4:利用
$range生成从1到数组长度的索引序列,再用$slice截取数组的前N个元素,生成所有前缀层级数组。这一步是核心,能自动补全父分类层级。 - 步骤6:用
$join将层级数组拼接为字符串,再用$concat在首尾添加>,还原成需求的路径格式。 - 步骤7:去重确保每个分类层级只保留一条记录。
- 步骤8:通过
$merge将结果写入目标集合,支持增量更新。
示例结果
处理分类>technology>televisions>4k>后,会生成三条记录:
{ "_id": ">technology>" } { "_id": ">technology>televisions>" } { "_id": ">technology>televisions>4k>" }
内容的提问来源于stack exchange,提问作者Sugafree
相关产品推荐
相关产品推荐

