MongoDB聚合将两个不同的字段合并为一个并获取计数

MongoDB aggregate merge two different fields as one and get count

本文关键字:一个 合并 获取 字段 两个 MongoDB      更新时间:2023-09-26

我在MongoDB中有以下数据:

[{id:3132, home:'NSH', away:'BOS'}, {id:3112, home:'ANA', away:'CGY'}, {id:3232, home:'MIN', away:'NSH'}]

是否可以使用聚合管道获取每个团队的总游戏计数?

期望的结果:

[{team: 'NSH', totalGames: 2}, {team:'MIN', totalGames: 1}, ...}]

我可以通过两个聚合调用分别将每个数组连接到自己的数组:

[{$group: {_id: "$home", gamesLeft: {$sum: 1}}}]

[{$group: {_id: "$away", gamesLeft: {$sum: 1}}}]

导致

var homeGames = [ { _id: 'NSH', totalGames: 1 }, { _id: 'SJS', totalGames: 2 }, ...]
var awayGames = [ { _id: 'NSH', totalGames: 1 }, { _id: 'SJS', totalGames: 4 }, ...]

但我真的想让它只用一个查询工作。如果不可能,那么使用 javascript 将这两个结果合并为一个的最佳方法是什么?

经过一番困惑,我找到了一种使用聚合管道完成它的方法。结果如下:

db.games.aggregate([{
        $project: {
            isHome: { $literal: [true, false] },
            home: true,
            away: true
        }
    }, {
        $unwind: '$isHome'
    }, {
        $group: {
            _id: { $cond: { if: '$isHome', then: '$home', else: '$away' } },
            totalGames: { $sum: 1 }
        }
    }
]);

如您所见,它由三个阶段组成。前两个旨在将每个文档复制到一个用于主队和另一个用于客队。为此,项目阶段首先在每个文档上创建一个包含真值和假值的新isHome字段,然后展开阶段将其拆分为包含真值或假值的单独文档。

然后在分组阶段,我们让isHome字段决定是在home还是away字段上进行分组。

如果我们可以在项目步骤中创建一个包含数组[$home, $away]team字段会更好,但 mongo 仅支持在此处添加数组文字,因此解决方法。