【问题标题】:Aggregate documents after limiting them by a certain amount for a specific property将特定属性的文档限制为一定数量后汇总文档
【发布时间】:2017-01-24 15:54:28
【问题描述】:

我需要找到所有用户的分数,只为每个用户挑选两个最好的分数,最后将这些分数相加来创建一个排行榜。

让我举个例子说明我正在寻找什么以及我已经尝试过但没有成功。

Users Collection:
[
  {user: "userA", score:10, game: 12},
  {user: "userA", score:20, game: 12},
  {user: "userA", score:7, game: 12},
  {user: "userB", score:10, game: 12},
  {user: "userB", score:3, game: 12},
  {user: "userB", score:7, game: 12}
]

我想要的结果是这样的:

[
  {user:"userA", score:30, game:12},
  {user:"userB", score:17, game:12}
]

我尝试过聚合的 mongo 方式,但不幸的是你不能 $sort, $limit 在聚合的 $group 阶段,这意味着你不能只选择两个最好的分数。

有没有办法通过处理简单的 find() 查询的返回文档,使用 mapReduce 甚至使用 Lodash 来做到这一点?

【问题讨论】:

    标签: mongodb mongoose lodash


    【解决方案1】:

    您可以使用lodash的_.sortBy()_.groupBy()_.map()得到每个用户的最高2个分数并将它们相加:

    var arr = [
      {user: "userA", score:10, game: 12},
      {user: "userA", score:20, game: 12},
      {user: "userA", score:7, game: 12},
      {user: "userB", score:10, game: 12},
      {user: "userB", score:3, game: 12},
      {user: "userB", score:7, game: 12}
    ];
    
    var result = _(arr) // start a lodash's chain
      .sortBy(function(value) { // sort the array descending
        return -value.score;
      })
      .groupBy('user') // group by the user
      .map(function(arr) { // map each user
        var score = arr[0].score + (arr[1] ? arr[1].score : 0); // the score should be a combination of the 1st two items (if there are two)
        return Object.assign({}, arr[0], { score, score }); // assign to new object, with the calculated score
      })
      .value(); // extract the result from the chain
    
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

    【讨论】:

    • 另外,为了完成,我认为应该在链的末尾有一个最终的 sortBy 以便有一个排序的排行榜。
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2022-06-12
    • 2017-08-12
    • 2021-08-14
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    相关资源
    最近更新 更多