Javascript 基于值折叠子文档的投影

Javascript 基于值折叠子文档的投影,javascript,mongodb,mongodb-query,aggregation-framework,Javascript,Mongodb,Mongodb Query,Aggregation Framework,我有一个数据结构,其中一个子文档包含一个部门ID数组,这些ID是同时包含ID和部门名称的对象。人们可能在许多部门,每个部门都有一个单独的ID,因此他们的记录可能如下所示: { "_id" : "xxxxx", "dept_ids" : [ { "dept_id" : "dd7867535", "dept_name" : "d1" }, { "dept_i

我有一个数据结构,其中一个子文档包含一个部门ID数组,这些ID是同时包含ID和部门名称的对象。人们可能在许多部门,每个部门都有一个单独的ID,因此他们的记录可能如下所示:

{ 
    "_id" : "xxxxx", 
    "dept_ids" : [
        {
            "dept_id" : "dd7867535", 
            "dept_name" : "d1"
        }, 
        {
            "dept_id" : "dl97087079", 
            "dept_name" : "d2"
        }
    ]
}
{ 
    "_id" : "xxxxx", 
    "d1" : "dd7867535",
    "d2" : "dl97087079"
}
我正在使用已知的部门子集组合一个聚合查询,我想使用“dept_name”的值来汇总这些值,因此生成的文档如下所示:

{ 
    "_id" : "xxxxx", 
    "dept_ids" : [
        {
            "dept_id" : "dd7867535", 
            "dept_name" : "d1"
        }, 
        {
            "dept_id" : "dl97087079", 
            "dept_name" : "d2"
        }
    ]
}
{ 
    "_id" : "xxxxx", 
    "d1" : "dd7867535",
    "d2" : "dl97087079"
}
我很难在聚合框架中找到这样做的方法。欢迎提出任何建议

谢谢,
Alex

如果您确实有一个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环境中,不是mongoshell,而是NodeJS之类的东西,您可以稍微清理一下语法。i、 使用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" }

因此,您实际上不需要通过聚合管道来处理事情,聚合管道可以非常简单地从客户端上接收的数据来完成。您没有“减少”任何数据,这实际上是聚合框架的要点。因此,像这样的转换实际上“应该”在对光标结果进行后处理时进行。

提供的答案中是否有您认为无法解决您的问题的内容?如果是,请对答案进行评论,以澄清哪些问题需要解决,哪些问题尚未解决。如果它确实回答了您提出的问题,那么请注意您提出的问题