使用 mongodb 按 reddit 算法对记录进行排序
Sorting records by reddit algorithm using mongodb
我正在尝试将 reddit 算法实现为我的应用程序中的排序选项,但我总是到处碰壁。
我开始使用此 (Sorting mongodb by reddit ranking algorithm) post 作为指导来实施。
我试着把它转换成c#;以下是我尝试进行转换。
var map = new BsonJavaScript(
@"function() {
function hot(score, date){
var order = log10(Math.max(Math.abs(score), 1));
var sign = score>0 ? 1 : score<0 ? -1 : 0;
var seconds = epochSeconds(date) - 1134028003;
var product = order + sign * seconds / 45000;
return Math.round(product*10000000)/10000000;
}
function log10(val){
return Math.log(val) / Math.LN10;
}
function epochSeconds(d){
return (d.getTime() - new Date(1970,1,1).getTime())/1000;
}
emit( hot(this.VoteCount, this.CreatedAt), this );
}"
);
var reduce = new BsonJavaScript(
@"function(){}"
);
var finalize = new BsonJavaScript(
@"{ 'out': { 'inline': 1 } }"
);
return db.Posts.MapReduce(new MapReduceArgs { MapFunction = map, ReduceFunction = reduce, FinalizeFunction = finalize }).GetResults();
他是我从实施中得到的结果;
他是真正的数据集。
出于某种原因,函数 returns 2 个对象而不是 4 个。
此外,对于 return 整个 post 对象以及计算出的分数,我需要修改什么?
如果有人能帮助我,我将不胜感激:)
提前致谢,
让
通过 2 次修改修复了它。
这 2 个资源非常有用;
http://docs.mongodb.org/manual/reference/command/mapReduce/#mapreduce-map-cmd
http://docs.mongodb.org/manual/reference/method/db.collection.mapReduce/#db.collection.mapReduce
首先,我更改了传递给发射的参数。我正在为 post 对象动态分配 "score" 值,并在其上分配 运行 热函数。然后我将 emit 的键参数作为对象键传递,并将值参数作为具有分值的新 post 对象传递。 **发出(键,值)
this.score = hot(this.VoteCount, this.CreatedAt);
emit( this._id, this );
然后我将获取结果的方式更改为;
db.Posts.MapReduce(new MapReduceArgs { MapFunction = map, ReduceFunction = reduce}).InlineResults
希望这对其他人有帮助:)
有空的时候我会post用这种计算分数的方法来做C#的benchmarks计算。
替代实施/更新:
我切换到 Hacker News 使用的更简单/更快的衰减算法,因为它仍然满足我的要求。 http://amix.dk/blog/post/19574
Score = (P-1) / (T+2)^G
where,
P = points of an item (and -1 is to negate submitters vote)
T = time since submission (in hours)
G = Gravity, defaults to 1.8 in news.arc
我正在尝试将 reddit 算法实现为我的应用程序中的排序选项,但我总是到处碰壁。
我开始使用此 (Sorting mongodb by reddit ranking algorithm) post 作为指导来实施。
我试着把它转换成c#;以下是我尝试进行转换。
var map = new BsonJavaScript(
@"function() {
function hot(score, date){
var order = log10(Math.max(Math.abs(score), 1));
var sign = score>0 ? 1 : score<0 ? -1 : 0;
var seconds = epochSeconds(date) - 1134028003;
var product = order + sign * seconds / 45000;
return Math.round(product*10000000)/10000000;
}
function log10(val){
return Math.log(val) / Math.LN10;
}
function epochSeconds(d){
return (d.getTime() - new Date(1970,1,1).getTime())/1000;
}
emit( hot(this.VoteCount, this.CreatedAt), this );
}"
);
var reduce = new BsonJavaScript(
@"function(){}"
);
var finalize = new BsonJavaScript(
@"{ 'out': { 'inline': 1 } }"
);
return db.Posts.MapReduce(new MapReduceArgs { MapFunction = map, ReduceFunction = reduce, FinalizeFunction = finalize }).GetResults();
他是我从实施中得到的结果;
他是真正的数据集。
出于某种原因,函数 returns 2 个对象而不是 4 个。 此外,对于 return 整个 post 对象以及计算出的分数,我需要修改什么?
如果有人能帮助我,我将不胜感激:)
提前致谢, 让
通过 2 次修改修复了它。
这 2 个资源非常有用; http://docs.mongodb.org/manual/reference/command/mapReduce/#mapreduce-map-cmd http://docs.mongodb.org/manual/reference/method/db.collection.mapReduce/#db.collection.mapReduce
首先,我更改了传递给发射的参数。我正在为 post 对象动态分配 "score" 值,并在其上分配 运行 热函数。然后我将 emit 的键参数作为对象键传递,并将值参数作为具有分值的新 post 对象传递。 **发出(键,值)
this.score = hot(this.VoteCount, this.CreatedAt);
emit( this._id, this );
然后我将获取结果的方式更改为;
db.Posts.MapReduce(new MapReduceArgs { MapFunction = map, ReduceFunction = reduce}).InlineResults
希望这对其他人有帮助:)
有空的时候我会post用这种计算分数的方法来做C#的benchmarks计算。
替代实施/更新: 我切换到 Hacker News 使用的更简单/更快的衰减算法,因为它仍然满足我的要求。 http://amix.dk/blog/post/19574
Score = (P-1) / (T+2)^G
where,
P = points of an item (and -1 is to negate submitters vote)
T = time since submission (in hours)
G = Gravity, defaults to 1.8 in news.arc