草庐IT

node.js - 匹配两个集合并在找不到匹配项时运行异步代码的最有效方法

coder 2023-11-05 原文

我有两个集合,一个包含我的静态项目,另一个包含该项目的反向地理编码结果。它们由 id 属性匹配。

我正在编写一个脚本,用于填充缺少项目的反向地理编码集合。

这是我当前的解决方案,它非常慢,但确实如此:

  • 获取静态项的总数
  • 从静态项目集合创建读取流
  • 对来自读取流的每个项目使用反向地理编码集合中的 find one
  • 如果项目存在,将计数器加1并忽略它
  • 如果 item 不存在,则从 API 中获取它,将其保存到集合中并将计数器加 1
  • 当 counter 等于 total count 时,表示所有项目都已获取, 因此解析函数

    function fetchMissingData(){
      return new Promise((resolve, reject) => {
        const staticData = Global.state.db.collection('static_data')
        const googleData = Global.state.db.collection('google_reverse_geocode')
    
      staticData.count((countErr, count) => {
        if (countErr) return reject(countErr)
        let counter = 0
        let fetched = 0
    
        function finishIfReady(){
          process.stdout.write(`Progress...(${counter}/${count}), (fetched total: ${fetched})\r`)
          if (count === counter) {
            resolve({ fetched, counter })
          }
        }
    
        staticData.find()
        .on('data', (hotel) => {
          googleData.findOne({ id: hotel.id }, (findErr, geocodedItem) => {
            if (findErr) return reject(findErr)
            if (geocodedItem) {
              counter++
              finishIfReady()
            } else {
              GMClient.reverseGeocode({ latlng: hotel.geo }, (err, response) => {
                if (err) return reject(err)
                googleData.insertOne({
                  id: hotel.id,
                  payload: response,
                }).then(() => {
                  fetched++
                  counter++
                  finishIfReady()
                }).catch(e => reject(e))
              })
            }
          })
        })
        .on('error', e => reject(e))
      })
    })
    }
    

是否有使用聚合框架的更优雅的解决方案,允许我在没有 O(n^{2}) O(nlogn) 复杂性的情况下实现相同的行为?

最佳答案

首先,实际的复杂度是 O(nlogn),因为 id 上的 findOne 使用二分查找。其次,虽然在这种情况下无法通过理论复杂度 O(nlogn),但有办法帮助您在实践中更快地编写代码。这就是我要做的:

function getIdOfAllGeoData() {
    // return an array of existing Geo data IDs
    return Global.state.db.collection('google_reverse_geocode')
        .find().toArray().map(o => o.id);
}

function getStaticDataMissingGeo(existingGeoDataIds) {
    const staticData = Global.state.db.collection('static_data');

    return staticData.find({
        id: {
            $nin: existingGeoDataIds
        }
    }).toArray();
}

function fetchMissingData() {
    const existingGeoDataIds = getIdOfAllGeoData();
    const staticDataMissingGeo = getStaticDataMissingGeo(existingGeoDataIds);

    // staticDataMissingGeo is all the static that need geo data
    // you can loop through this array, get each items geo data and insert to database

    // ...
}

最后,您可以使用bulk 操作来加快速度,这样会快很多。另外,我上面的 mongo 相关代码可能不正确,作为一个想法。

关于node.js - 匹配两个集合并在找不到匹配项时运行异步代码的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48208898/

有关node.js - 匹配两个集合并在找不到匹配项时运行异步代码的最有效方法的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  4. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  5. ruby - 匹配未转义的平衡定界符对 - 2

    如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。

  6. ruby - 匹配大写字母并用后续字母填充,直到一定的字符串长度 - 2

    我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种

  7. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  8. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  9. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  10. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

随机推荐