Mongo 元素数组聚合

问题描述 投票:0回答:1

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

有这样的输入数据

[
  {
    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' }} } 
]

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

javascript mongodb
1个回答
0
投票

对于您的问题,您可能需要使用

$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
开始。

© www.soinside.com 2019 - 2024. All rights reserved.