我有一堆表示一场比赛中得分的文件.我想按用户ID对分数进行分组并求和,但有一个问题:可以得负分,但累加和不应该低于零.因此,例如,如果用户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'],
              },
            ],
          },
        },
      },
    },
  }
]

这取决于points是否以正确的顺序被推到pointDeltas上(earnedDate,升序).

从实验上看,这种情况似乎确实发生了.但这是有保证的吗?

我注意到$first个运算符状态的official documentation:

返回每个组的第一个文档中的值.只有在对文档进行排序的情况下才定义顺序.

这似乎是在暗示文档是按顺序处理的,尽管这一原则是否也适用于使用$push还不是$push%清楚.同一页上的$push的文档没有类似的注释.

这种行为是肯定的还是巧合的?无论哪种方式,我都找不到任何防弹的答案.

推荐答案

根据$push中的例子,对文件进行排序.

我建议你在https://jira.mongodb.org/岁时立案.在那里提出您的问题和/或在文档中请求延期.

如果你想绝对确定,那么你可以用这个:

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

Mongodb相关问答推荐

如何在MongoDB中正确解析佛年?

MongoDB:如何通过增量向量递增整数向量

如何将空值单独分组?

MongoDB shell:如何删除列表以外的所有集合

MongoDB - 家庭作业(job)帮助.不确定如何在 mongodb 中访问文档中的变量

如何在 Spring-Data-MongoDB 中使用 $facet、$addFields 和 $function

mongoose中的 required是什么意思?

增加嵌套对象中的值?

从 PHP 打印 MongoDB 日期

mongo _id 字段重复键错误

更新 mongoengine 中的嵌入文档列表

MongoDB 聚合 $divide 计算字段

如何使用 MongoDB 建模 likes投票系统

如何在mongodb中删除数组的第n个元素

带有部分字符串的mongoose文本搜索

在 mongodb 聚合框架中执行 case-statement

将 MongoCursor from ->find() 转换为数组

如何使用服务器实例指定 mongodb 用户名和密码?

Mongoose:Model.create 和 Collection.insert 有什么区别

Mongo 条件为key doesn't exist?