You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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数组] }结构:

  1. $group:按device_id分组,把对应的所有date收集到一个数组里
  2. $arrayToObject:把分组后的device_id和dates数组转换成动态键值对
  3. $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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:12:26