Rails 4 ActiveRecord查询自引用has_many关联的空关联

时间:2016-04-28 20:57:45

标签: ruby-on-rails ruby ruby-on-rails-4

以下是设置:

# app/models/booking.rb

class Booking < ActiveRecord::Base
  # Associations
  belongs_to :parent_booking, class_name: "Booking"
  has_many :child_bookings, class_name: "Booking", foreign_key: "parent_booking_id"
end

这不是必需的关系,因此并非所有预订都有parent_booking或child_bookings。

尝试创建一个查询,该查询返回所有没有任何child_bookings的预订的ActiveRecord :: Relation,无论是否存在parent_booking。

以下示例(基于this SO question)适用于不同模型之间关系的场景。但是,由于记录在同一个表中,因此它不能与自引用关系一起使用。相反,它返回一个没有parent_booking的所有预订的ActiveRecord :: Relation。

Booking.includes(:child_bookings).where(bookings: { parent_booking_id: nil })

以下内容返回正确的对象,但效率极低,因为它必须为每条记录查询数据库。此外,它将它作为数组而不是ActiveRecord :: Relation返回(更关注效率低下)。

Booking.select { |b| b.child_bookings.empty? }

我很可能忽略了一个简单的解决方案,但广泛的搜索还没有发现任何东西。谢谢!

3 个答案:

答案 0 :(得分:1)

我添加counter cache,然后查询Booking.where(child_booking_count: 0)

答案 1 :(得分:1)

查询0个子记录的一种方法是:

parent_ids = Booking.parent_booking_ids
Booking.where('id NOT IN (?)',parent_ids)

希望它会返回所需的记录。

答案 2 :(得分:0)

我认为效率低下来自于急切的负载。如果你只是做一个标准的左连接,我认为你会发现性能很好:

Booking.joins("LEFT JOIN bookings child_bookings ON child_bookings.parent_booking_id = bookings.id").where(child_bookings: {id: nil})

我知道您失去了使用AR关联的能力,但ActiveRecord尚未决定包含左连接。如果你想要它们,我已经制作了一个可以用来添加它的要点here以及用这种类型的东西制作的附加方法:without:那么你可以写{ {1}}