ActiveRecord 连接 - Return 仅完全匹配
ActiveRecord joins - Return only exact matches
我有三个模型 Outfit
、Product
和一个连接模型 OutfitProduct
(Outfit 通过 OutfitProducts 有很多产品)。
我想查找仅包含完全匹配产品的服装。
到目前为止我有这个
def by_exact_products(products)
joins(outfit_products: :product)
.where(outfit_products: { product: products })
.group("outfits.id")
.having('count(outfits.id) = ?', products.size)
end
以上 return 包含我正在搜索的产品的任何服装,即使它不是完全匹配的。我希望 return 只有完全匹配的服装。
示例:
假设我们有以下由以下产品组成的服装:
outfit_1.products = [product_1, product_2, product_3, product_4]
outfit_2.products = [product_1, product_2]
outfit_3.products = [product_1, product_2, product_3]
如果我将 [product_1, product_2, product_3]
传递给我的查询,它将 return outfit_1
和 outfit_3
- 我只希望它 return outfit_3
这是完全匹配。
更新(更多信息)
使用包含三个产品的数组调用查询会生成以下查询:
SELECT "outfits".*
FROM "outfits"
INNER JOIN "outfit_products"
ON "outfit_products"."outfit_id" = "outfits"."id"
INNER JOIN "products"
ON "products"."id" = "outfit_products"."product_id"
WHERE "outfit_products"."product_id" IN ( 18337, 6089, 6224 )
GROUP BY outfits.id
HAVING ( Count(outfits.id) = 3 )
我们先来看看为什么会这样。您使用以下场景:
outfit_1.products = [product_1, product_2, product_3, product_4]
outfit_2.products = [product_1, product_2]
outfit_3.products = [product_1, product_2, product_3]
这将有以下 outfit_products
table:
outfit_id | product_id
----------|-----------
1 | 1
1 | 2
1 | 3
1 | 4
2 | 1
2 | 2
3 | 1
3 | 2
3 | 3
当您添加限制时:
WHERE "outfit_products"."product_id" IN ( 1, 2, 3 )
它将消除行:
outfit_id | product_id
----------|-----------
1 | 4
产品 1 保留 3 条记录,当您对记录进行分组和计数时,产品 1 的结果值为 3。这意味着当前查询将仅检查提供的最少产品(也就是确保所有提供的产品都存在)。
要同时消除产品多于所提供产品的记录,您必须添加第二个计数。没有上述限制的产品算在哪。
def by_exact_products(products)
# all outfits that have at least all products
with_all_products = joins(outfit_products: :product)
.where(outfit_products: { product: products })
.group("outfits.id")
.having('count(outfits.id) = ?', products.size)
# all outfits that have exactly all products
joins(outfit_products: :product)
.where(id: with_all_products.select(:id))
.group("outfits.id")
.having('count(outfits.id) = ?', products.size)
end
这将select所有至少拥有所有提供的产品的服装,并统计他们的产品总数。
我有三个模型 Outfit
、Product
和一个连接模型 OutfitProduct
(Outfit 通过 OutfitProducts 有很多产品)。
我想查找仅包含完全匹配产品的服装。
到目前为止我有这个
def by_exact_products(products)
joins(outfit_products: :product)
.where(outfit_products: { product: products })
.group("outfits.id")
.having('count(outfits.id) = ?', products.size)
end
以上 return 包含我正在搜索的产品的任何服装,即使它不是完全匹配的。我希望 return 只有完全匹配的服装。
示例: 假设我们有以下由以下产品组成的服装:
outfit_1.products = [product_1, product_2, product_3, product_4]
outfit_2.products = [product_1, product_2]
outfit_3.products = [product_1, product_2, product_3]
如果我将 [product_1, product_2, product_3]
传递给我的查询,它将 return outfit_1
和 outfit_3
- 我只希望它 return outfit_3
这是完全匹配。
更新(更多信息)
使用包含三个产品的数组调用查询会生成以下查询:
SELECT "outfits".*
FROM "outfits"
INNER JOIN "outfit_products"
ON "outfit_products"."outfit_id" = "outfits"."id"
INNER JOIN "products"
ON "products"."id" = "outfit_products"."product_id"
WHERE "outfit_products"."product_id" IN ( 18337, 6089, 6224 )
GROUP BY outfits.id
HAVING ( Count(outfits.id) = 3 )
我们先来看看为什么会这样。您使用以下场景:
outfit_1.products = [product_1, product_2, product_3, product_4] outfit_2.products = [product_1, product_2] outfit_3.products = [product_1, product_2, product_3]
这将有以下 outfit_products
table:
outfit_id | product_id
----------|-----------
1 | 1
1 | 2
1 | 3
1 | 4
2 | 1
2 | 2
3 | 1
3 | 2
3 | 3
当您添加限制时:
WHERE "outfit_products"."product_id" IN ( 1, 2, 3 )
它将消除行:
outfit_id | product_id
----------|-----------
1 | 4
产品 1 保留 3 条记录,当您对记录进行分组和计数时,产品 1 的结果值为 3。这意味着当前查询将仅检查提供的最少产品(也就是确保所有提供的产品都存在)。
要同时消除产品多于所提供产品的记录,您必须添加第二个计数。没有上述限制的产品算在哪。
def by_exact_products(products)
# all outfits that have at least all products
with_all_products = joins(outfit_products: :product)
.where(outfit_products: { product: products })
.group("outfits.id")
.having('count(outfits.id) = ?', products.size)
# all outfits that have exactly all products
joins(outfit_products: :product)
.where(id: with_all_products.select(:id))
.group("outfits.id")
.having('count(outfits.id) = ?', products.size)
end
这将select所有至少拥有所有提供的产品的服装,并统计他们的产品总数。