You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB先$sort再$group,$push的顺序是否有官方保障?

关于MongoDB聚合中$push排序顺序的疑问

需求与实现

我有一批代表游戏得分的文档,希望按用户ID分组计算积分总和,但有特殊规则:得分可为负,但累计积分不能低于0。例如用户1的得分顺序为1、2、-5、3,最终得分应为3,因为-5只会将积分降至0而非-2。

我编写了如下聚合管道,经测试可实现该需求:

[
  {
    $sort: {
      earnedDate: 1,
    },
  },
  {
    $group: {
      _id: '$userId',
      pointDeltas: {
        $push: '$points',
      },
      userId: {
        $first: '$userId',
      },
    },
  },
  {
    $project: {
      userId: 1,
      points: {
        $reduce: {
          input: '$pointDeltas',
          initialValue: 0,
          in: {
            $max: [
              0,
              {
                $add: ['$$value', '$$this'],
              },
            ],
          },
        },
      },
    },
  }
]

核心疑问

该管道依赖$push按earnedDate升序将points存入pointDeltas,实验中顺序符合预期,但不确定此行为是否有官方保障。我注意到$first操作符的官方文档指出:“返回每组第一个文档的值,仅当文档已排序时顺序才确定”,这似乎暗示文档按顺序处理,但不确定该原则是否适用于$push,且$push的文档无类似说明。请问此行为是有保障的还是偶然现象?


解答

这个行为是有官方保障的。

MongoDB聚合管道是按阶段依次执行的,每个阶段的输出会作为下一个阶段的输入。当你先通过$sort阶段对全局文档按earnedDate升序排序后,后续$group阶段处理每组内的文档时,会严格遵循这个排序后的顺序。虽然$push的官方文档没有像$first那样单独强调顺序,但$group阶段会保留$sort传入的文档顺序,因此$push会按该顺序将points元素存入数组。

你的管道逻辑是完全正确的,$reduce部分也准确实现了“累计积分不低于0”的规则,可以放心使用。

内容的提问来源于stack exchange,提问作者Aurast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:37:16