【问题标题】:Batch processing/updating Monogdb documents in Nodejs在 Node Js 中批量处理/更新 Mongodb 文档
【发布时间】:2014-11-24 21:54:48
【问题描述】:

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

在 NodeJS 中最好的方法是什么?


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

【问题讨论】:

    标签: node.js mongodb mongoose batch-processing


    【解决方案1】:

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

    最简单的就是写一个很简单的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
    

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

    【讨论】:

    • 这让您不再需要 node.js、mongoose 和其他中介。
    • 尝试使用node-cron github.com/ncb000gt/node-cron 它会将所有内容保留在您的节点应用程序中
    • 这是一个 mongo shell 脚本。并且在撰写本文时无法轻松导入任何外部库,例如 moment、node-cron 或任何便利。是的,你可以写一个节点脚本(甚至可能更好),上面的代码会放在里面。
    • Mongo shell 脚本与 NodeJS 驱动的性能差异是什么?
    • python async mongo 驱动程序的请求/秒比同步驱动程序高出 10 倍,但这是多个读取操作(查找与更新)。我相当有信心 mongo shell 不使用异步驱动程序。
    【解决方案2】:

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

    【讨论】:

    • 这在查找单个帖子或按其他因素排序的组时非常有用(因为我已经知道我正在查找哪些帖子),但我真正想要的是查询“排名靠前的”帖子按分数排序。为此,我需要对整个集合运行“calcScore()”操作,然后才能对其进行查询。
    【解决方案3】:

    此处未表示的另一个选项是 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])
    

    【讨论】:

      猜你喜欢
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-07
      • 1970-01-01
      • 2011-05-25
      • 1970-01-01
      相关资源
      最近更新 更多