And*_*art 38 ruby activerecord ruby-on-rails
这可能是一个简单的问题,但我似乎正在拔头发找到一个优雅的解决方案.我有两个ActiveRecord模型类,它们之间有一个has_one和belongs_to关联:
class Item < ActiveRecord::Base
has_one :purchase
end
class Purchase < ActiveRecord::Base
belongs_to :item
end
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种优雅的方法来查找所有Item对象,这些对象没有与它们关联的购买对象,理想情况下不需要is_purchased在Item上使用布尔值或类似属性.
现在我有:
purchases = Purchase.all
Item.where('id not in (?)', purchases.map(&:item_id))
Run Code Online (Sandbox Code Playgroud)
哪个有效,但对我来说似乎效率低下,因为它正在执行两个查询(并且购买可能是一个巨大的记录集).
运行Rails 3.1.0
dim*_*uch 37
这是非常常见的任务,SQL OUTER JOIN通常可以正常工作.例如,看看这里.
在你的情况下尝试使用类似的东西
not_purchased_items = Item.joins("LEFT OUTER JOIN purchases ON purchases.item_id = items.id").where("purchases.id IS null")
Run Code Online (Sandbox Code Playgroud)
bro*_*son 28
找到另外两种铁路方式:
Item.includes(:purchase).references(:purchase).where("purchases.id IS NULL")
Item.includes(:purchase).where(purchases: { id: nil })
Run Code Online (Sandbox Code Playgroud)
从技术上讲,第一个示例在没有'references'子句的情况下工作,但Rails 4在没有它的情况下吐出弃用警告.
Reg*_*ieB 13
更简洁的@dimuch解决方案是使用left_outer_joinsRails 5中引入的方法:
Item.left_outer_joins(:purchase).where(purchases: {id: nil})
Run Code Online (Sandbox Code Playgroud)
请注意,在left_outer_joins调用中:purchase是单数的(它是has_one声明创建的方法的名称),并且在where子句中:purchases是复数(这里是该id字段所属的表的名称.)
missingRails 6.1 添加了在类中调用的查询方法ActiveRecord::QueryMethods::WhereChain。
它返回一个带有左外连接和父子模型之间的 where 子句的新关系,以识别缺失的关系。
例子:
Item.where.missing(:purchase)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12011 次 |
| 最近记录: |