[英]Rails Not query on entire Where clause
是否有一种直接的方法可以使用 ActiveRecord/ARel 否定整个where
表达式? 似乎where.not()
,当给出参数的散列时,会单独否定每个表达式,而不是用单个 SQL NOT
否定整个事物。
Thing.where.not(attribute1: [1,2], attribute2: [3,4], attribute3: [5,6])
select * from things where attribute1 NOT IN (1,2) AND attribute2 NOT IN (3,4) AND attribute3 NOT IN (5,6)
不过,这不是我想要做的。 我想用一个NOT
否定整个 where 子句。
select * from things where NOT(attribute1 IN (1,2) AND attribute2 IN (3,4) AND attribute3 IN (5,6))
在布尔符号中,Rails 似乎喜欢否定 WHERE 子句的每个组件,如下所示:
!(a) && !(b) && !(c)
但我想否定整个表达式:
! [ (a) && (b) && (c) ]
使用德摩根定律,我可以将查询写为!a || !b || !c
!a || !b || !c
!a || !b || !c
,但这会导致一些相当长和丑陋的代码(Rails 5 和or
长度较短,但仍然很丑)。 我希望使用 ActiveRecord 或 ARel 时缺少一些语法糖?
我正在编写 Ransack Equality Scope(例如 _eq)来搜索条件及其相反的条件。
scope :can_find_things_eq, ->(boolean = true) {
case boolean
when true, 'true'
where(conditions_for_things)
when false, 'false'
where.not(conditions_for_things)
end
}
def self.ransackable_scopes(_auth_object = nil)
%i[can_find_things_eq]
end
如果我使用上面的 Rails 5 建议和我开始的例子,我可以让我的否定查询工作......但代码又长又丑。
where.not(attribute1: [1,2]).or(where.not(attribute2:
[3,4)).or(where.not(attribute3: [5,6))
链接 Ors 和 WhereNots 有效,但它的可读性不是很强。 有没有更好的方式来否定这个where
除了不必手动否定它/逻辑使用德摩根定律?
谢谢!
你可以试试这个:
Thing.where.not(attribute1: [1,2]).or(Thing.where.not(attribute2: [3,4]).or(Thing.where.not(attribute3: [5,6])
这以与您需要的完全相同的方式生成查询:
!condition1 || !condition2 || !condition3
您可以使用 Arel 生成所需的结果,如下所示:
table = Thing.arel_table
clause = Arel::Nodes::Not.new(
table[:attribute1].in([1,2]).and(
table[:attribute2].in([2,3]).and(
table[:attribute3].in([5,6])
)))
Thing.where(clause)
或者
Thing.where.not(
table[:attribute1].in([1,2]).and(
table[:attribute2].in([2,3]).and(
table[:attribute3].in([5,6])
)))
如果您使用的是 Rails 7,则可以使用invert_where 。 这将完全按照您的需要形成查询
! [ (a) && (b) && (c) ]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.