Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何在Rails中有效地对模型进行评级和检索平均评级_Ruby On Rails - Fatal编程技术网

Ruby on rails 如何在Rails中有效地对模型进行评级和检索平均评级

Ruby on rails 如何在Rails中有效地对模型进行评级和检索平均评级,ruby-on-rails,Ruby On Rails,我有三种型号,用户、场地、评级,如下所示: class User < ActiveRecord::Base has_many :ratings end class Venue < ActiveRecord::Base has_many :ratings end class Rating < ActiveRecord::Base belongs_to :user belongs_to :venue end class用户

我有三种型号,用户、场地、评级,如下所示:

class User < ActiveRecord::Base
  has_many :ratings
end

class Venue < ActiveRecord::Base
  has_many :ratings
end

class Rating < ActiveRecord::Base
  belongs_to :user
  belongs_to :venue
end
class用户
用户可以从0-5对场馆进行评分。用户可以根据自己的意愿频繁地对场馆进行评分,而且他们的评分通常与同一用户在同一场馆内的评分不同,这两个用户在几分钟内就创建了同一场馆

我希望能够提供一个地点的平均评级从过去的一小时,但是我只想考虑一个单一的评级从每一个用户的时间段。因此,如果一个用户在过去一小时内多次对同一个场馆进行评分,则只考虑他们最近的评分

目前我有:

class Venue < ActiveRecord::Base
  has_many :ratings

  def past_hour_average
    ratings = self.ratings.where(:created_at => 1.hour.ago..Time.now).uniq_by(&:user_id)
    # loop through each record and compute average
    sum = 0
    ratings.each do |rating|
      sum += rating.value
    end
    return sum / ratings.size
  end
end
上课地点1.hour.ago..Time.now).uniq_by(&:user_id)
#循环遍历每个记录并计算平均值
总和=0
评级。每个do |评级|
总和+=额定值
结束
返回值/额定值。大小
结束
结束
然而,这种方法似乎效率低下。每次我想要一个场馆的评级,我都要计算它。
假设有许多用户经常对单个场馆进行评分,那么计算平均评分的更好方法是什么?

我认为这应该是可行的:

def past_hour_average
  ratings = self.ratings.where(created_at: 1.hour.ago..Time.now).order(:created_at).group(:user_id)

  ratings.sum(:value) / ratings.count
end
如果返回的是每个用户最早的评分,而不是最近的评分,则可能只需要反向排序


这正是您的代码所做的。。。它只是让数据库为您计算总和,而不是在ruby代码中手动计算。

我认为这应该可以:

def past_hour_average
  ratings = self.ratings.where(created_at: 1.hour.ago..Time.now).order(:created_at).group(:user_id)

  ratings.sum(:value) / ratings.count
end
如果返回的是每个用户最早的评分,而不是最近的评分,则可能只需要反向排序


这正是您的代码所做的。。。它只是让数据库为您计算总和,而不是在ruby代码中手动计算。

您确定这种计算的效率会成为一个问题吗?我认为这是不太可能的,除非你的站点体验“强>非常,非常/强”重读负载。 但这确实很重要,这里有一件简单的事情你可以做,这可能会有点帮助:

 def past_hour_average
   @past_hour_average ||= begin
     # calculation here
   end
 end
这将确保在单个请求的空间内,单个场馆的计算不会超过一次

如果您需要更好的解决方案,并且您已经进行了检查以确保这确实是一个问题,那么您可以缓存计算结果,如果缓存的时间超过一定的分钟数,则可以使其无效。我不会在这里为MemCached(等)而烦恼。我会做一些类似的事情:

 class Venue
   @@avg_rating_cache = {}

   def past_hour_average
     if avg,time = @@avg_rating_cache[self.id] && time > (Time.now - 10.minutes)
       @@avg_rating_cache[self.id] = [avg, Time.now]
       return avg
     end

     value = calculation_here
     @@avg_rating_cache[self.id] = [value, Time.now]
     value
   end
 end

这将直接在每个应用程序进程的内存中缓存结果(因此访问MemCached缓存不会产生额外的开销/延迟)。如果您有超过10000个场地,则需要在添加新的场地时将其从缓存中逐出,以防止过度使用内存。

您确定此计算的效率会成为一个问题吗?我认为这是不太可能的,除非你的站点体验“强>非常,非常/强”重读负载。 但这确实很重要,这里有一件简单的事情你可以做,这可能会有点帮助:

 def past_hour_average
   @past_hour_average ||= begin
     # calculation here
   end
 end
这将确保在单个请求的空间内,单个场馆的计算不会超过一次

如果您需要更好的解决方案,并且您已经进行了检查以确保这确实是一个问题,那么您可以缓存计算结果,如果缓存的时间超过一定的分钟数,则可以使其无效。我不会在这里为MemCached(等)而烦恼。我会做一些类似的事情:

 class Venue
   @@avg_rating_cache = {}

   def past_hour_average
     if avg,time = @@avg_rating_cache[self.id] && time > (Time.now - 10.minutes)
       @@avg_rating_cache[self.id] = [avg, Time.now]
       return avg
     end

     value = calculation_here
     @@avg_rating_cache[self.id] = [value, Time.now]
     value
   end
 end

这将直接在每个应用程序进程的内存中缓存结果(因此访问MemCached缓存不会产生额外的开销/延迟)。如果您有超过10000个场地,则需要在添加新的场地时从缓存中逐出条目,以防止内存过度使用。

我不熟悉rails中的缓存,但会研究一下。您不必担心负载,这可能是对的。谢谢我不熟悉rails中的缓存,但会深入研究。您不必担心负载,这可能是对的。谢谢