使用带有活动记录的连接 table 时如何连接模型的多个实例?
How to join with multiple instances of a model when using a join table with active record?
这是针对使用 PostgreSQL 的 Rails 5 / Active Record 5。
假设我有两个模型:Product
和 Widget
。 Product
has_many
小部件和 Widget
has_many
产品通过名为 products_widgets
.
的连接 table
我想编写一个查询来查找与 both widget 和 id=37
and widget 相关联的所有产品id=42
.
小部件
其实我有一个id列表,但是如果我能写出上面的查询,我一般都能解决这个问题
请注意,此查询的更简单版本是查找与 关联的所有小部件或者 与 id=37
或 [=41] 关联的小部件=] 带有 id=42
的小部件,您可以这样写:
Product.joins(:products_widgets).where(products_widgets: {widget_id: [37, 42]})
但这不是我需要的。
作为初学者:在纯 SQL 中,您可以用 exists
条件来表达查询:
select p.*
from product p
where
exists (
select 1
from products_widgets pw
where pw.product_id = p.product_id and pw.widget_id = 37
)
and exists (
select 1
from products_widgets pw
where pw.product_id = p.product_id and pw.widget_id = 42
)
在活动记录中,我们可以尝试直接在where
条件下使用原始子查询:
product
.where('exists(select 1 from products_widgets where product_id = product.product_id and widget_id = ?)', 37)
.where('exists(select 1 from products_widgets where product_id = product.product_id and widget_id = ?)', 42)
我认为使用 .arel.exist
也可能有效:
product
.where(products_widgets.where('product_id = product.product_id and widget_id = ?', 37).arel.exists)
.where(products_widgets.where('product_id = product.product_id and widget_id = ?', 42).arel.exists)
这是针对使用 PostgreSQL 的 Rails 5 / Active Record 5。
假设我有两个模型:Product
和 Widget
。 Product
has_many
小部件和 Widget
has_many
产品通过名为 products_widgets
.
我想编写一个查询来查找与 both widget 和 id=37
and widget 相关联的所有产品id=42
.
其实我有一个id列表,但是如果我能写出上面的查询,我一般都能解决这个问题
请注意,此查询的更简单版本是查找与 关联的所有小部件或者 与 id=37
或 [=41] 关联的小部件=] 带有 id=42
的小部件,您可以这样写:
Product.joins(:products_widgets).where(products_widgets: {widget_id: [37, 42]})
但这不是我需要的。
作为初学者:在纯 SQL 中,您可以用 exists
条件来表达查询:
select p.*
from product p
where
exists (
select 1
from products_widgets pw
where pw.product_id = p.product_id and pw.widget_id = 37
)
and exists (
select 1
from products_widgets pw
where pw.product_id = p.product_id and pw.widget_id = 42
)
在活动记录中,我们可以尝试直接在where
条件下使用原始子查询:
product
.where('exists(select 1 from products_widgets where product_id = product.product_id and widget_id = ?)', 37)
.where('exists(select 1 from products_widgets where product_id = product.product_id and widget_id = ?)', 42)
我认为使用 .arel.exist
也可能有效:
product
.where(products_widgets.where('product_id = product.product_id and widget_id = ?', 37).arel.exists)
.where(products_widgets.where('product_id = product.product_id and widget_id = ?', 42).arel.exists)