MongoDB聚合管道中如何匹配categoryId与子文档键
解决方案:MongoDB聚合中匹配categoryId与categoryTypes的键
首先需要明确:MongoDB里对象的键本质是字符串类型,即便你写入时用数字格式(如2),存储后实际是"2"。因此数值型的categoryId需要先转为字符串,才能和categoryTypes的键匹配。
场景1:筛选出categoryId对应键存在于categoryTypes中的文档
使用$match结合$expr,将categoryTypes转为数组后检查键的存在:
db.collection.aggregate([ { $match: { $expr: { $in: [ { $toString: "$categoryId" }, { $map: { input: { $objectToArray: "$categoryTypes" }, as: "item", in: "$$item.k" } } ] } } } ])
逻辑说明:
$objectToArray把categoryTypes转换为[{k: "1", v: "hello world"}, ...]格式的数组$map提取数组中所有的键(k字段)$in判断categoryId转成字符串后是否在键数组内
场景2:新增字段获取categoryId对应的categoryTypes值
如果需要在聚合中添加字段,取出匹配的对应值,可使用以下两种方式:
方式1:用$map+$arrayElemAt实现
db.collection.aggregate([ { $addFields: { matchedCategoryValue: { $arrayElemAt: [ { $map: { input: { $objectToArray: "$categoryTypes" }, as: "item", in: { $cond: [ { $eq: [{ $toString: "$categoryId" }, "$$item.k"] }, "$$item.v", null ] } } }, 0 ] } } }, // 可选:过滤无匹配结果的文档 { $match: { matchedCategoryValue: { $ne: null } } } ])
方式2:用$filter+$first更简洁实现
db.collection.aggregate([ { $addFields: { matchedCategoryValue: { $let: { vars: { matchedItem: { $first: { $filter: { input: { $objectToArray: "$categoryTypes" }, cond: { $eq: [{ $toString: "$categoryId" }, "$$this.k"] } } } } }, in: "$$matchedItem.v" } } } } ])
逻辑说明:
$filter从转换后的数组中筛选出键与categoryId匹配的元素$first取出唯一匹配的元素(因为键是唯一的)$let提取该元素的v字段(即对应的值)
内容的提问来源于stack exchange,提问作者RK65
相关产品推荐
相关产品推荐

