需要进行数据聚合,以汇总根和子表中的数据

具有这样的输入数据

[
  {
    id: ID,
    points: 10,
    sources: [{
      sourceId: 's1',
      sourcePoints: 6,
    },
    {
      sourceId: 's2',
      sourcePoints: 4,
    }]
  }, 
  {
    id: ID,
    points: 2,
    sources: [{
      sourceId: 's1',
      sourcePoints: 2,
    }]
  }
];

我想得到这个摘要

{
  id: ID,
  points: 12 // sum
  sources: {
    s1: { sourcePoints: 8 } // sum of all s1 from all records for sourceId = s1 and id = ID
    s2: { sourcePoints: 4 } // same as above, for sourceId = s2 and id = ID
    ... // sources can be N
  }
}

对于我来说,从根中求和很简单

[
 { $match: { id: ID } },
 { $group: { _id: $id, sum: { $sum: '$points' }} } 
]

但是我不知道如何从数组中加和

推荐答案

对于您的问题,您可能需要使用$arrayToObject操作符,因为您可能有N个名称未知的信号源.

一种解决办法如下:

db.collection.aggregate([
  {
    $match: {
      id: "ID"
    }
  },
  {
    "$unwind": "$sources"
  },
  {
    $group: {
      _id: {
        mainId: "$id",
        "sourceId": "$sources.sourceId"
      },
      sumPerSoureId: {
        $sum: "$sources.sourcePoints"
      }
    }
  },
  {
    $group: {
      _id: "$_id.mainId",
      totalPoints: {
        $sum: "$sumPerSoureId"
      },
      keyVal: {
        $push: {
          "k": "$_id.sourceId",
          "v": {
            "sourcePoints": "$sumPerSoureId"
          }
        }
      }
    }
  },
  {
    $project: {
      _id: 0,
      id: "$_id",
      points: "$totalPoints",
      sources: {
        "$arrayToObject": "$keyVal"
      }
    }
  }
])

你可以在mongoplayground.号上亲自试一下.

提供的解决方案可能没有针对数百万个文档进行优化,因为我一开始就使用了两个$unwind.

Javascript相关问答推荐

从连接字符串创建客户端时,NodeJS连接到CosmosDB失败

如何在Angular中插入动态组件

如何在angular中从JSON值添加动态路由保护?

有没有可能使滑动img动画以更快的速度连续?

如何从调整大小/zoom 的SVG路径定义新的d属性?""

将旋转的矩形zoom 到覆盖它所需的最小尺寸&S容器

如何将Openjphjs与next.js一起使用?

如何控制Reaction路由加载器中的错误状态?

WhatsApp Cloud API上载问题:由于MIME类型不正确而导致接收&Quot;INVALID_REQUEST";错误

更改预请求脚本中重用的JSON主体变量- Postman

以Angular 实现ng-Circle-Progress时出错:模块没有导出的成员

同一类的所有div';S的模式窗口

变量在导入到Vite中的另一个js文件时成为常量.

如何 for each 输入动态设置输入变更值

按什么顺序接收`storage`事件?

是否可以将Select()和Sample()与Mongoose结合使用?

如何使用画布在另一个内部绘制一个较小但相同的形状,同时保持恒定的边界厚度?

如何使用Reaction路由导航测试挂钩?

将字符串解释为数字;将其重新编码为另一个基数

在AgGrid中显示分组行的单元格值