Ruby on rails Rails订单记录符合大多数条件
对关联中存在的元素进行排序,其中第一个元素将是最选定关联中存在的元素。 换句话说,大多数关联的排序元素都存在于给定的列表中。 这听起来很复杂,所以这里是一个工作示例,但速度非常慢 我们想按大多数司机能驾驶的程度对汽车进行分类Ruby on rails Rails订单记录符合大多数条件,ruby-on-rails,ruby,performance,Ruby On Rails,Ruby,Performance,对关联中存在的元素进行排序,其中第一个元素将是最选定关联中存在的元素。 换句话说,大多数关联的排序元素都存在于给定的列表中。 这听起来很复杂,所以这里是一个工作示例,但速度非常慢 我们想按大多数司机能驾驶的程度对汽车进行分类 # 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
# 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)
Db表如下所示:
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
左连接
驱动\u级别
如何,但只有那些在动态\u驱动\u id
中具有驱动\u id
的级别(希望动态\u驱动\u id
不是来自用户,否则容易发生sql注入)?然后您可以根据驾驶级别的计数进行分组和排序
它看起来是这样的:
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)")
首先,您应该在此处使用
where
和references
:
dynamic_drivers_ids = [1,2,3,100,5]
@cars = Car.includes(:driving_level).
references(:driving_level).
where(driving_level: {id: dynamic_drivers_ids})
这里发生的事情是,它将连接表cars
和driving\u level
,并仅拉取driving\u level
记录,这些记录具有这些id(您不必执行:e.driving\u level.map(&:driver\u id)和dynamic\u drivers\u id
)。您将不再提取所有驾驶级别的记录。
这应该会大大加快
次要:按关联排序。最简单的方法是使用列,它计算我们的关联,然后在上面排序:
@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')
这将返回正确的顺序和正确的关联记录。如果driving\u levels
包含driver\u id
1,2,3100,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
select\u clause=您的数据库是什么?似乎汽车属于驾驶级别
。所以看到driving\u level.map(&:driver\u id)
很奇怪。请提供模型代码。我已经用表更新了问题。我认为这属于codereview,因为它是代码优化。有一个错误PG::UndefinedColumn:错误:列“driving_levels_size”不存在不确定是否可以将数组插入sql字符串:(是的,我的错误,您需要括号。已编辑