Rails 5:ActiveRecord OR 查询

Posted

技术标签:

【中文标题】Rails 5:ActiveRecord OR 查询【英文标题】:Rails 5: ActiveRecord OR query 【发布时间】:2015-12-21 13:46:05 【问题描述】:

如何在 Rails 5 ActiveRecord 中进行or 查询?另外,是否可以在 ActiveRecord 查询中将orwhere 链接起来?

【问题讨论】:

May be of help 【参考方案1】:

Rails 5 中将提供在 ActiveRecord 查询中链接 or 子句和 where 子句的功能。请参阅related discussion and the pull request。

因此,您将能够在 Rails 5 中执行以下操作:

要获得带有id 1 或2 的post

Post.where('id = 1').or(Post.where('id = 2'))

其他一些例子:

(A && B) || C:

    Post.where(a).where(b).or(Post.where(c))

(A || B) && C:

    Post.where(a).or(Post.where(b)).where(c)

【讨论】:

我怎样才能得到 (A || B) && (C || D)。我试过 Post.where(a).or(Post.where(b)).where(c).or(Post.where(d)) 但它产生为: (A || B) && C || D @Imran 我相信它会是Post.where(a).or(Post.where(b)).where(Post.where(c).or(Post.where(d))) 这应该创建 (a || b) && (c || d) @Imran 这似乎对我不起作用:我得到ArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation) 等价于.or,它接受一个关系并产生一个and是.merge。 (A || B) && ( C || D) 可以通过 Post.where(a).or(Post.where(b)).merge(Post.where(c).or(Post.where(d) ))) @MathieuJ。它是 ActiveRecord::Relation#merge。 api.rubyonrails.org/classes/ActiveRecord/…【参考方案2】:

我们不需要等待 rails 5 使用这个 OR 查询。我们也可以将它与rails 4.2.3 一起使用。有一个反向端口here。

感谢 Eric-Guo 提供 gem where-or,现在我们也可以使用此 gem 在 >= rails 4.2.3 中添加此 OR 功能。

【讨论】:

【参考方案3】:

(只是对 K M Rakibul Islam 答案的补充。)

使用范围,代码可以变得更漂亮(取决于眼睛看):

scope a,      ->  where(a) 
scope b,      ->  where(b) 

scope a_or_b, ->  a.or(b) 

【讨论】:

【参考方案4】:

我需要做一个 (A && B) || (C && D) || (E && F)

但是在 Rails 5.1.4 的当前状态中,这太复杂了,无法使用 Arel 或链来完成。 但我仍然想使用 Rails 生成尽可能多的查询。

所以我做了一个小技巧:

在我的模型中,我创建了一个名为 sql_whereprivate 方法:

private
  def self.sql_where(*args)
    sql = self.unscoped.where(*args).to_sql
    match = sql.match(/WHERE\s(.*)$/)
    "(#match[1])"
  end

接下来在我的范围内,我创建了一个数组来保存 OR

scope :whatever, -> 
  ors = []

  ors << sql_where(A, B)
  ors << sql_where(C, D)
  ors << sql_where(E, F)

  # Now just combine the stumps:
  where(ors.join(' OR '))

这将产生预期的查询结果: SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F)).

现在我可以轻松地将它与其他范围等结合起来,而不会出现任何错误的 OR。

我的 sql_where 采用正常的 where 子句参数的美妙之处在于: sql_where(name: 'John', role: 'admin') 将生成(name = 'John' AND role = 'admin')

【讨论】:

我认为您可以使用.merge 作为 && 的等价物,并构建一个适当的树来捕获您的括号。类似于...(scopeA.merge(scopeB)).or(scopeC.merge(scopeD)).or(scopeE.merge(scopeF)),假设每个作用域都类似于Model.where(...) 在使用合并之前检查一下 - github.com/rails/rails/issues/33501【参考方案5】:

Rails 5 可以使用or 子句和where。 例如。

User.where(name: "abc").or(User.where(name: "abcd"))

【讨论】:

以上是关于Rails 5:ActiveRecord OR 查询的主要内容,如果未能解决你的问题,请参考以下文章

markdown 禁用ActiveRecord for Rails 4,5

如何存储和比较:ActiveRecord 中的符号(Ruby on Rails)

Mysql 5.7 json 数据类型,在 Rails 5 中使用 activerecord 查询

如何将此查询转换为ActiveRecord(Rails 5)

Rails 5 - 如何为activerecord获取serializable_hash?

Rails ActiveRecord 查询不等于