ruby-on-rails - 大表上的 Rails 计算

标签 ruby-on-rails ruby postgresql rails-activerecord tf-idf

我会尽力解释我的问题。 我创建了一个表,它表示基于购买的用户 (user_models) 之类的文本模型。我还有一个表 term_tfs,它将 user_id 和 term(varchar(200)) 存储为 PK 以及一些其他数字列。它基本上是一个矩阵,其中包含术语及其模型的数字 tf_idf_norm 值。现在我需要进行比较用户模型的计算,所以我需要为一个用户加载这个矩阵,并与不同用户的其他矩阵进行比较。

问题是,term_tfs 表真的很大(大约 13.5 行),我需要为至少有 5 次(1285 位用户)或 10 次(9333)购买的用户获取矩阵。当我从 term_tfs 表中进行选择时,大约需要 20-40 毫秒。但是我需要一些方法来让其他 9000 名用户进行比较。将每个 user_id 查询到 term_tfs 中的天真的方法需要 10 秒以上的时间进行一次比较,如果我想为接下来的几千个用户进行这种比较并将其存储在其他地方,这会很慢。

def self.compare_user(user_id)
  @results = Hash.new
  # @user_ids = UserModel.where.not(user_id: user_id).pluck(:user_id)
  @user_ids = UserModel.get_useful_ids(user_id, 5)
  @user_matrix = TermTf.where(user_id: user_id).pluck(:term,  :tf_idf_norm)
  @user_terms = @user_matrix.map { |a| a[0] }


  @user_ids.each do |id|

    matrix = TermTf.where(user_id: id).pluck(:term, :tf_idf_norm)
    store_result( compare_matrix(matrix), id )

  end

  sort_results( @results )
end

def self.compare_matrix(matrix)
  sim = 0

  matrix.each do |t|
    unless ( ( i = @user_terms.index(t[0]) ).nil? )
      sim += t[1] * @user_matrix[i][1]
    end
  end

  sim
end

def self.store_result(similarity, id)
  @results[id] = similarity
end

基准输出(9333 user_ids):

puts Benchmark.measure {@user_ids.each{|id| TermTf.where(user_id:  id).pluck(:term, :tf_idf_norm)}}
4.890000   0.180000   5.070000 ( 11.019708)

这似乎是一种相当糟糕/缓慢的方法,那么如何让它更快呢?我很想听听其他解决这个问题的方法,比如使用 Ruby 或 SQL。

最佳答案

要将 Beartech 的方法放入 Rails 代码而不是创建 View ,您可以这样做(需要根据您的需要进行调整):

subquery = TermTf.where(user_id: user_id).select(:term,  :tf_idf_norm).to_sql
result = TermTf.joins("INNER JOIN (#{subquery }) sub on sub.term = term_tfs.term")
         .select("term_tfs.user_id as user_id, sum(sub.tf_idf_norm * term_tfs.tf_idf_norm) as tf_idf_norm_sum")
         .where(user_id: @user_ids)
         .where.not(user_id:  user_id)
         .group('term_tfs.user_id')
         .all

关于ruby-on-rails - 大表上的 Rails 计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40918735/

相关文章:

ruby-on-rails - Rails 什么时候响应 'transfer-encoding' 与 'content-length' ?

ruby-on-rails - rails 4 collection_select 多个嵌套属性未正确保存

css - 如何根据类值更改框颜色

ruby - 为什么 fork 在 Minitest 测试中以非零退出?

ruby-on-rails - 使用 Facebooker 和 Ruby on Rails 的 session 问题

ruby-on-rails - rails,为新路由添加一个参数

ruby-on-rails - PG::Error: 错误:关系 schema_migrations 的权限被拒绝

postgresql - 当双引号内有\n(换行符)时,如何使用 pgloader 或 PostgreSQL 副本解析 CSV?

python - 如果 postgresql 不存在(列数和值不同)如何创建动态插入

spring - 在使用 liquibase 填充数据库后,如何更正 Postgres 序列?