批量处理/更新Node Js中的Mongodb文档

时间:2014-11-24 21:54:48

标签: node.js mongodb mongoose batch-processing

我想定期(每隔5分钟左右)处理/更新Mongodb集合中的每个文档,并将结果保存回数据库。更新函数需要在每个文档上执行实际代码(据我所知),因为它需要执行计算,例如获取时间戳的差异并使用Math.pow的指数,standard MongoDB update operators不盖

在NodeJS中执行此操作的最佳方法是什么?


完整背景:我正在尝试实施Hacker News ranking algorithm,这与时间有关。 discussion I've seen around this涉及使用单独的线程/进程来定期更新文档的分数。

3 个答案:

答案 0 :(得分:2)

没有浪费来回调查,似乎你有字段我将调用points,初始创建时间created_date,然后是result的ycombinator (p - 1) / (t + 2)^1.5 < / p>

最简单的是写一个非常简单的3班次mongo shell script

db.ycombinator.find().forEach(function(doc) {
   var diff = ISODate() - doc.created_date; // subtract date using some form of date ISODate is available in mongo shell
   var hours = diff.tomagicalhours(); // some regulr javascript
   var result = (doc.points - 1) / Math.pow((hours + 2), 1.5); // perform yc algo
   db.ycombinator.update({"_id":doc._id}, {$set:{"result": result} }); // write back into same collection and field, result
})

进入文件ycombinator_update.js,然后执行5分钟的crontab。

*/5 * * * * mongo ycombinator_update.js

在写操作期间,读取的性能会明显变慢,这取决于该集合中的记录数。

答案 1 :(得分:1)

您可以在查找时根据文档时间戳分配分数,并仅将原始时间戳保留在数据库中。由于得分无论如何都是时间戳的函数,因此评分算法可以在未修改的数据上包含指数衰减逻辑。如果要按分数搜索,则可以将分数转换为时间戳。

答案 2 :(得分:0)

此处未显示的另一个选项是 MongoDB MapReduceAggregation frameworks

这两个框架都提供了一种迭代集合中所有元素并将一些结果输出到不同集合的方法。聚合API不直接包含我们在HN算法中计算1.5指数所需的基元(无$sqrt$pow),而是there is a workaround

我不确定哪个方法对于这个用例是最有效的(以及它与MongoDB shell脚本suggested by Gabe Rainbow的比较)。

我相信下一步是在一个单独的进程中运行更新操作,该进程可以使用类似cron的方式进行调度,也可以使用fork通过节点应用程序本身启动更新操作以下逻辑:

On request for front page:
    # when did we last update the scores for the front page?
    if last_update was within last X minutes:
        return list sorted by score right away
    else
        fork a process to sort the front page
        last_update := Date.Now
        return list sorted by score (either right away [stale], or after the update completes [takes a while])