2017-08-17 23 views
-1

存在于关联中的订单元素,其中第一个元素将是存在于最多选定关联中的元素。 换句话说,按给定列表存在大多数assosietions的顺序元素。 听起来很复杂,所以在这里的工作示例,但超级慢。Rails通过大多数条件的订单记录符合

我们希望将汽车进行排序,以最驱动器可驱动他们

# we have some ids of driver seleted by user 
dynamic_drivers_ids = [1,2,3,100,5] 

@cars = Car.all.includes(:driving_levels) 
@cars.sort_by {|e| (e.driving_level.map(&:driver_id) & dynamic_drivers_ids).size * -1 } 

需要大约1个第二加载,只有20辆。 但现在我们有100辆车的情况,并且需要数十年来计算它。

我们如何编写SQL请求来订购? 它不工作,但显示出一些逻辑:

Car.includes(:driving_levels).order("driving_level.id IN = ? AND driving_level.size", dynamic_drivers_ids) 

数据库表的样子:

class Car 
    has_many :driving_levels 
    has_many :drivers, through: driving_levels 


class DrivingLevel 
    belongs_to :car 
    belongs_to :driver 

class Driver 
    has_many :driving_levels 
    has_many :cars, through: driving_levels 
+0

你的db是什么? –

+0

看来'汽车belongs_to driving_level'。所以看到'driving_level.map(&:driver_id)'很奇怪。请提供型号代码。 –

+0

我已更新表格 – GEkk

回答

0

什么左加入driving_levels但只有那些在dynamic_drivers_idsdriver_id(希望dynamic_drivers_ids不来自用户,否则它是sql-injection-prone)?那么你可以根据驾驶等级的数量进行分组和排序?

这将是这样的:

Car 
    .joins("LEFT OUTER JOIN driving_levels ON 
      driving_levels.id = cars.driving_level_id AND 
      driving_level.driver_id IN (#{dynamic_drivers_ids})") 
    .group(:id).order("COUNT(driving_levels.id)") 
+0

不知道你是否可以插入数组到SQL字符串:( – GEkk

+0

是的,我的错误,你需要编辑 –

0

首先,你应该使用wherereferences这里:

dynamic_drivers_ids = [1,2,3,100,5] 

@cars = Car.includes(:driving_level). 
      references(:driving_level). 
      where(driving_level: {id: dynamic_drivers_ids}) 

这里发生的是它将连接表carsdriving_level,和只拉driving_level记录,其中包含这些ID(您不需要做:e.driving_level.map(&:driver_id) & dynamic_drivers_ids)。你不会再把所有的driving_level记录全部取出​​来。 这应该大大加快。

次要:按关联排序。最简单的方法是在它使用的列,其计算我们的协会,然后顺序:

@cars = Car.select('COUNT(driving_levels.id) as driving_levels_size'). 
      includes(:driving_level). 
      references(:driving_level). 
      where(driving_level: {id: dynamic_drivers_ids}). 
      group('cars.id, driving_levels.id'). 
      order('driving_levels_size') 

这应返回你正确的顺序和关联设定的正确的记录。

+0

有一个错误PG :: UndefinedColumn:错误:列“driving_levels_size”不存在 – GEkk

0

如果driving_levels包含driver_id 1,2,3,100,5的记录,请尝试此操作。

select_clause = <<~SQL 
    cars.*, 
    (SELECT count(DISTINCT driver_id) FROM driving_levels 
    WHERE driver_id IN (1,2,3,100,5) 
     OR car_id=cars.id) as driver_cnt 
SQL 

Car 
    .select(select_clause) 
    .order('driver_cnt DESC') 
    .to_a