使用MongoDB聚合函数查询数组:如何获取预期输出?
MongoDB聚合管道实现文档转结构化列表求助
我有如下MongoDB样本文档,需要将其转换为指定格式的输出结果。作为MongoDB新手,我尝试用$match、聚合函数、$projection来实现预期结果,但当前的聚合管道仅返回部分结果,请求帮助。
样本文档
{ "_id": "act_8347100017075469", "firstName": "Akki", "lastName": "Dlast", "accountNumber": "12397124", "feature": { "feature-name1": { "baseCode": "bc1", "serviceCode": [ // serviceCode的元素数量和名称是动态的 "SC1", "SC2", "SC3" ] }, "feature-name2": { "baseCode": "bc2", "serviceCode": [ // serviceCode的元素数量和名称是动态的 "SC21", "SC22" ] }, "feature-name3": { "baseCode": "bc3", "serviceCode": [ "SC41", "SC42", "SC43" ] } } }
预期输出
Account No feature-name, base-code, svc-code 12397124, feature-name1, bc1, SC1 12397124, feature-name1, bc1, SC2 12397124, feature-name1, bc1, SC3 12397124, feature-name2, bc2, SC21 12397124, feature-name2, bc2, SC22 12397124, feature-name3, bc3, SC41 12397124, feature-name3, bc3, SC42 12397124, feature-name3, bc3, SC43
注:修正了预期输出里重复的行,按实际数据展开后的正确结果呈现
我尝试的聚合管道及结果
db.collection.aggregate([ { $match: { "feature.feature-name1.baseCode": { $exists: true } } }, { $project: { accountNbr: 1, "feature": "feature-name1", "baseCode": "$feature.feature-name1.baseCode" } } ])
返回的部分结果:
[ { "_id": "act_8347100017075469", "baseCode": "bc1", "feature": "feature-name1" } ]
解决方案
你的问题在于当前管道只针对单个固定feature处理,且没有展开serviceCode数组。要实现预期的结构化输出,需要用到$objectToArray、$unwind等聚合阶段,完整管道如下:
db.collection.aggregate([ // 保留需要的字段,同时把feature对象转为键值对数组 { $project: { _id: 0, accountNumber: 1, featureEntries: { $objectToArray: "$feature" } } }, // 展开featureEntries数组,每个feature单独成文档 { $unwind: "$featureEntries" }, // 展开每个feature下的serviceCode数组,每个服务码单独成文档 { $unwind: "$featureEntries.v.serviceCode" }, // 投影成预期的字段名 { $project: { "Account No": "$accountNumber", "feature-name": "$featureEntries.k", "base-code": "$featureEntries.v.baseCode", "svc-code": "$featureEntries.v.serviceCode" } } ])
管道说明:
$project+$objectToArray:把feature这个嵌套对象转换成[{k: "feature-name1", v: {...}}, ...]的数组格式,解决feature名称动态的问题。$unwind(第一次):将feature数组展开,每个feature成为独立文档。$unwind(第二次):将每个feature下的serviceCode数组展开,每个服务码成为独立文档。- 最终
$project:将字段重命名为预期的名称,同时排除不需要的_id。
执行这个管道后,就能得到和预期一致的结构化结果。
内容的提问来源于stack exchange,提问作者Gagd
相关产品推荐
相关产品推荐

