为排名算法分页一个猫鼬mapReduce



我使用MongoDB mapReduce来编写排名提要算法,它几乎可以工作,但最新实现的是分页。map reduce支持结果限制,但知道我在使用mongoose,我如何实现基于结果的最新查看_id的偏移(跳过)?

这是我写的程序:

o = {};
o.map = function() {
    //log10(likes+comments) / elapsed hours from the post creation
    emit(Math.log(this.likes + this.comments + 1) / Math.LN10 / Math.abs((now - this.createdAt) / 6e7 + 1), this);
};
o.reduce = function(key, values) {
    //sort the values, when they have the same score
    values.sort(function(a, b) {
        a.createdAt - b.createdAt;
    });
    //serialize the values, because mongoose does not support multiple returned values
    return JSON.stringify(values);
};
o.scope = {now: new Date()};
o.limit = 15;
Posts.mapReduce(o, function(err, results) {
    if (err) return console.log(err);
    console.log(results);
});

此外,如果mapReduce不是一条路,你是否建议其他人如何实现这样的东西?

您需要的是一个页面分隔符,它不是您所说的最近查看的id,而是您的排序属性。在这种情况下,它似乎是公式Math.log(this.likes + this.comments + 1) / Math.LN10 / Math.abs((now - this.createdAt) / 6e7 + 1)

因此,在您的映射中,Reduce query需要保存上述公式的where值。或者具体地说,'formula>=. And also it needs to hold the value of createdAt at the last page, since you don't sort by that. (Assuming createdAt is unique). So your查询of mapReduce would say,其中:FormulaExpression,createdAt:{$lt:lastCreatedAt}`

如果您确实允许多个相同的createdAt值,那么您必须在数据库本身之外玩一点。

所以你只需要按公式搜索。

理想情况下,这会为您提供一个恰好具有该值的元素,然后对下一个元素进行排序。因此,在回复模块调用程序时,从数组中删除第一个元素(并确保您实际要求的结果比您需要的结果多)。

现在,由于您允许多个类似的值,因此需要另一个标识道具,例如对象id或created_at。您的使用者(此模块的调用方)必须同时提供(last value of the scorecreatedAt of the last object)。假设你有一个页面正好被拆分在中间——一个或多个对象在上一个页面上,另一个对象设置在下一个页面。你不需要简单地删除最高值(因为上一页已经提供了相同的分数),还可能从顶部删除几个分数。

然后它就变得非常疯狂了,因为可能你的整个页面都已经被服务了——比较_id,在模块调用程序为你提供的_id之后寻找第一个_id。或者查看数据,确定有多少类似的匹配值,尝试从mapReduce中获得至少与实际页面大小一样多的值。

除此之外,我会用聚合来做这件事,它应该更具性能。

相关内容

  • 没有找到相关文章

最新更新