在针对特定属性限制一定数量的文档之后汇总文档

时间:2016-09-16 12:08:51

标签: mongodb mongoose lodash

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

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

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方式,但不幸的是你不能在$ group阶段对$ $ sort,$ limit进行限制,这意味着你不能只选择两个最佳分数。

通过操作简单的find()查询的返回文档,有没有办法可以使用mapReduce甚至Lodash?

1 个答案:

答案 0 :(得分:0)

您可以使用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>