Ruby on Rails - 比较两个大型数组以获得非匹配结果的最有效方法

时间:2013-11-11 10:26:05

标签: ruby-on-rails ruby arrays ruby-on-rails-2

我的应用程序中有一些遗留代码,它将模型的所有表行与供应商的API调用结果进行比较。

这个工作正常,直到上周,表格行数和供应商的结果数量都大幅增加。

表基数从1,657变为59,699,API返回的结果数量约为150,000。

代码正在做的是查看API结果以检查是否找不到当前表行数据,如果是,那么当前数据在数据库中是孤立的,因为它存在于那里而不是供应商给出的数据我们。

查看150,000个结果以检查是否某些内容对我来说听起来并不是特别聪明,而且看起来是这样的,因为我甚至不知道这需要多长时间才能运行由于视图在大约半小时后仍在加载:/

控制器

@telco_numbers = TelcoNumber.orphaned_in_db

模型

def self.orphaned_in_db
  db_numbers = self.find(:all)
  listed_numbers = self.all_telco
  orphaned_numbers = []
  db_numbers.each do |db|
    scan = listed_numbers.select{ |l| l.number == db.number}
    orphaned_numbers.push(db) if scan.empty?
  end
  return orphaned_numbers
end

def self.some_telco(per_page, page = 1)
  page = 1 if page.nil?
  # this is the first api call which returns a link which is then used for the next api call
  api_call = TelcoApiv3.new("post", "/numbers/#{TelcoApiv3.account_id}/allocated/all")
  listed_numbers = TelcoApiv3.poll(api_call.response["link"])
  return listed_numbers.collect do |ln| 
    ln.store("countrycode", ln["country_code"])
    TelcoNumber.new ln
  end
end

def self.all_telco(page = 1)
  listed_numbers = some_telco(@@max_nlist_results, page)
  if listed_numbers.length == @@max_nlist_results
    return listed_numbers.concat(all_telco(page + 1))
  else
    return listed_numbers
  end
end

示例API结果格式:

[{"country_code":"44","number":"1133508889"},....

number与模型表中的number列相关。 (它存储为varchar而不是数字)。

此外,api结果按升序返回,因此已经排序,所以我认为这会使事情变得更好?

1 个答案:

答案 0 :(得分:1)

为什么不尝试数组差异?首先制作两个db_numbers&数组。 listing_numbers并从较大的数组中减去较小的数组:

def self.orphaned_in_db
  db_numbers = self.find(:all).map{|x| x.number}
  listed_numbers = self.all_telco.map{|x| x.number}
  orphaned_numbers = db_numbers - listed_numbers
  orphaned_results = self.find(orphaned_numbers)
  return orphaned_results
end

当我从db_numbers中减去lists_numbers时,我将得到不匹配的结果集。现在,您可以在数据库中的orphaned_numbers基础上找到结果。它会快得多。感谢