ruby-on-rails - 如何在Rails中使用AND而不是OR来查询has_and_belongs_to?
问题描述
这可能是一个简单的问题,但我正在努力。这是我正在尝试做的事情:
我有一门课,我们称之为Car
HABTM Features
。所以:
class Car < ApplicationRecord
has_and_belongs_to_many :features
end
class Feature < ApplicationRecord
has_and_belongs_to_many :cars
end
假设我创建了以下数据:
bumper = Feature.create(name: "Bumper")
windshield = Feature.create(name: "Windshield")
Car.create(name: "Toyota", features: [bumper, windshield])
所以现在我有一个具有两个功能的汽车实例。
假设有人传入(例如,通过 Web 表单)功能列表。我想做一个查询,只查找具有所有传入功能的汽车。
因此,如果传入的功能列表是:["Bumper", "Brakes"]
那么它不应该找到那辆“丰田”汽车。但是,如果功能列表是["Bumper"]
它应该,或者如果功能列表是["Windshield","Bumper"]
它应该。
这显然不起作用,因为它是一个“或”:
Car.joins(:features).where(features: {name: ["Bumper","Brakes"]})
返回“Toyota”汽车,因为“Bumper”匹配加入该汽车的功能。在这种情况下,我想要它做的是返回[]
(没有汽车)。
如何为这种情况设置 Rails 查询?
注意:给定汽车的特征数量是可变的,传入的特征列表的数量也是可变的。我只想将传入的功能列表与功能相结合,并且只返回具有基于功能列表的所有功能的汽车。
我知道这可能很容易,但我似乎无法弄清楚。
解决方案
让我们从一个更简单的案例开始,Feature
有一个car_id
字段,Car has_many features
.
然后你可以这样查询:
使用ARRAY_AGG聚合函数返回 a
subquery
,每一行都有feature names
a 的所有car
,例如[{car_id: 1, names: ["Bumper", "Brakes"]}, ...]
Car
JOIN
Feature
by ,然后使用@>subquery
运算符过滤。cars
# Example code, may need to tweak a bit
sql = Feature.select(car_id, ARRAY_AGG(name) as names)
.group(:car_id)
.order(:car_id)
.to_sql
Car.joins("INNER JOIN (#{sql}) AS features ON cars.id = features.user_id")
.where("features.names @> ARRAY[?]::varchar[]", names)
在您的情况下,您使用has_and_belongs_to_many
了 ,因此您需要进行一些调整以使用joining table
,例如car_features
.
推荐阅读
- swift - SwiftUI 媒体播放器视图 - 在主视图中嵌入小播放器
- javascript - 我无法在我的 javascript 项目中在 firebase auth 中创建用户。我应该怎么办?
- c# - 在 C# 中使用反射获取方法内的所有方法
- c++ - 为什么虚拟继承会导致指针偏移?
- powershell - PowerShell - 多个 Get-Date 调用返回不同的时间格式/文化
- javascript - 我无法理解如何使用 MEAN 编写在一群人之间分配资金的逻辑
- javascript - 如何将用户身份验证添加到 docsifyjs
- jquery - minpointlength 和 datalabels 的问题在 columnrange 中重叠
- php - ACF 分类法只返回孩子 - 想要父母和孩子
- node.js - 运行“nodemon app”命令时出错