投影根据价值折叠子文档

时间:2018-05-07 22:39:16

标签: javascript mongodb mongodb-query aggregation-framework

我的数据结构带有一个包含部门ID数组的子网,这些部门ID是包含ID和部门名称的对象。人们可能在很多部门,并且每个部门都有一个单独的ID,因此他们的记录可能如下所示:

{ 
    "_id" : "xxxxx", 
    "dept_ids" : [
        {
            "dept_id" : "dd7867535", 
            "dept_name" : "d1"
        }, 
        {
            "dept_id" : "dl97087079", 
            "dept_name" : "d2"
        }
    ]
}

我将聚合查询与已知的部门子集放在一起,我想使用" dept_name"的值。汇总值,以便生成的文档如下所示:

{ 
    "_id" : "xxxxx", 
    "d1" : "dd7867535",
    "d2" : "dl97087079"
}

我在汇总框架中找不到这样做的方法。任何建议都会受到欢迎。

谢谢, 亚历

1 个答案:

答案 0 :(得分:0)

如果你实际上有一个支持$replaceRoot$arrayToObject的MongoDB,那么你可以使用它:

db.collection.aggregate([
  { "$replaceRoot": {
    "newRoot": {
      "$mergeObjects": [
        { "_id": "$_id" },
        { "$arrayToObject": {
          "$map": {
            "input": "$dept_ids",
            "in": { "k": "$$this.dept_name", "v": "$$this.dept_id" }
          }
        }}
      ]
    }
  }}
])

但你甚至不需要它,而只是简单地转换返回的文件:

db.collection.find().map(d =>
  Object.assign(
    { _id: d._id },
    d.dept_ids.reduce((acc,dep) => Object.assign(acc,{ [dep.dept_name]: dep.dept_id }), {})
  )
);

在现代ECMASCRIPT环境中,不是Mongo shell,而是NodeJS,你可以稍微清理一下语法。即使用NodeJS驱动程序:

const mapper = ({ _id, dept_ids }) => ({
  _id, ...dept_ids.reduce((acc, { dept_name: k, dept_id: v }) => ({ ...acc, [k]: v }),{})
});

let results = await db.collection('departments').find().map(mapper).toArray();

两者产生相同的结果:

{ "_id" : "xxxxx", "d1" : "dd7867535", "d2" : "dl97087079" }

因此,您真的不需要通过聚合管道处理事务,这可以通过客户端上接收的数据完成。您并没有“减少”任何数据,这实际上是聚合框架的重点。所以这样的转换确实“应该”在后处理光标结果时完成。