MongoDB技术问题:如何将字段值作为字段键返回文档?
嘿,我来帮你搞定这个MongoDB聚合的需求!你提到想用$mapReduce,不过其实现在MongoDB官方更推荐用**聚合管道(Aggregation Pipeline)**来做这类分组操作,不仅效率更高,语法也更直观。咱们先从你的数据和期望结果入手,一步步实现。
首先先明确你的原始数据:
const sampleData = [ { _id: '1', device_id: 'ML39A-341D4-UI041', date: '2018-03-28T00:00:00.000Z' }, { _id: '2', device_id: 'ML39A-341D4-UI041', date: '2018-03-29T00:00:00.000Z' }, { _id: '3', device_id: 'D4YK2-R2D20-KYPI9', date: '2018-04-01T00:00:00.000Z' } ];
方法一:用聚合管道实现(强烈推荐)
这个方式通过几个聚合阶段就能完成你要的{ device_id: [dates数组] }结构:
$group:按device_id分组,把对应的所有date收集到一个数组里$arrayToObject:把分组后的device_id和dates数组转换成动态键值对$replaceRoot:把生成的键值对作为结果的根文档,让结构完全匹配你的期望
具体代码如下:
db.collection.aggregate([ // 可选:如果只需要特定device_id,先加这个过滤阶段 // { $match: { device_id: "ML39A-341D4-UI041" } }, // 按device_id分组,收集所有date到dates数组 { $group: { _id: "$device_id", dates: { $push: "$date" } } }, // 转换为{ device_id: [dates] }的结构 { $project: { _id: 0, deviceData: { $arrayToObject: [[{ k: "$_id", v: "$dates" }]] } } }, // 把deviceData作为根文档,输出最终结构 { $replaceRoot: { newRoot: "$deviceData" } } ])
运行后得到的结果完全符合你的期望:
[ { "ML39A-341D4-UI041": ["2018-03-28T00:00:00.000Z", "2018-03-29T00:00:00.000Z"] }, { "D4YK2-R2D20-KYPI9": ["2018-04-01T00:00:00.000Z"] } ]
方法二:用$mapReduce实现(满足你的初始尝试方向)
如果你一定要用$mapReduce,也可以通过定义map、reduce和finalize函数来实现:
db.collection.mapReduce( // Map函数:将每个文档的device_id作为键,date作为值emit出去 function() { emit(this.device_id, this.date); }, // Reduce函数:把相同键的所有date值合并成数组 function(key, values) { return values; }, { // Finalize函数:把结果转换成你要的{ device_id: [dates] }格式 finalize: function(key, reducedValue) { const result = {}; result[key] = reducedValue; return result; }, // 指定输出方式为inline,直接返回结果(也可以输出到新集合) out: { inline: 1 } } )
这个方法的结果里,value字段就是你要的结构:
[ { "_id": "ML39A-341D4-UI041", "value": { "ML39A-341D4-UI041": ["2018-03-28T00:00:00.000Z", "2018-03-29T00:00:00.000Z"] } }, { "_id": "D4YK2-R2D20-KYPI9", "value": { "D4YK2-R2D20-KYPI9": ["2018-04-01T00:00:00.000Z"] } } ]
小提醒:优先用聚合管道
相比$mapReduce,聚合管道是MongoDB原生优化的功能,执行速度更快,尤其是处理大数据量的时候;而且聚合管道的语法是声明式的,更容易阅读和维护,不需要写JavaScript函数,出错概率也更低。
内容的提问来源于stack exchange,提问作者levelone
相关产品推荐
相关产品推荐

