如何在 Rails 3 ActiveRecord 中进行 OR 查询。我发现的所有示例都只有 AND 查询。
编辑:自 Rails 5 起 OR 方法可用。参见 ActiveRecord::QueryMethods
Post.where(column: 'something').or(Post.where(other: 'else'))
如果要对一列的值使用 OR 运算符,可以将数组传递给 .where
,ActiveRecord 将使用 IN(value,other_value)
:
Model.where(:column => ["value", "other_value"]
输出:
SELECT `table_name`.* FROM `table_name` WHERE `table_name`.`column` IN ('value', 'other_value')
这应该在单个列上实现相当于 OR
在 Rails 3 中,它应该是
Model.where("column = ? or other_column = ?", value, other_value)
这也包括原始 sql,但我认为 ActiveRecord 中没有办法进行 OR 操作。你的问题不是菜鸟问题。
Rails 5 添加了 or,因此现在在 Rails 版本大于 5 的应用程序中这更容易:
Model.where(column: value).or(Model.where(other_column: other_value)
这也处理 nil
值
Page.where("pages.column = ? or pages.other_column = ?", value, other_value)
column IS NULL or other_column IS NULL
。我认为 Rails 提供了一种获取 sql 片段的中间方法(where_clause 之类的),让我挖掘一下。这在这里可能有用。
使用ARel
t = Post.arel_table
results = Post.where(
t[:author].eq("Someone").
or(t[:title].matches("%something%"))
)
生成的 SQL:
ree-1.8.7-2010.02 > puts Post.where(t[:author].eq("Someone").or(t[:title].matches("%something%"))).to_sql
SELECT "posts".* FROM "posts" WHERE (("posts"."author" = 'Someone' OR "posts"."title" LIKE '%something%'))
matches
将为 sqlite 生成 LIKE
(默认情况下不区分大小写)和在 postgres 上生成 ILIKE
(需要像运算符一样显式不区分大小写)。
Rails/ActiveRecord 的更新版本可能会原生支持这种语法。它看起来类似于:
Foo.where(foo: 'bar').or.where(bar: 'bar')
如本拉取请求中所述 https://github.com/rails/rails/pull/9052
现在,只需坚持以下工作就可以了:
Foo.where('foo= ? OR bar= ?', 'bar', 'bar')
更新:根据 https://github.com/rails/rails/pull/16052,Rails 5 将提供 or
功能
更新:功能已合并到 Rails 5 分支
or
现在在 Rails 5 中可用,但不能以这种方式实现,因为它需要传递 1 个参数。它需要一个 Arel 对象。查看接受的答案
or
方法,则它可以工作:但如果在随后被链接的范围内使用它,则可能会打破您的期望。
Rails 最近将其添加到 ActiveRecord 中。它看起来在 Rails 5 中发布。已经致力于掌握:
https://github.com/rails/rails/commit/9e42cf019f2417473e7dcbfcb885709fa2709f89
Post.where(column: 'something').or(Post.where(other: 'else'))
# => SELECT * FROM posts WHERE (column = 'something') OR (other = 'else)
Rails 5 带有一个 or
方法。 (link to documentation)
此方法接受 ActiveRecord::Relation
对象。例如:
User.where(first_name: 'James').or(User.where(last_name: 'Scott'))
如果你想使用数组作为参数,下面的代码在 Rails 4 中有效:
query = Order.where(uuid: uuids, id: ids)
Order.where(query.where_values.map(&:to_sql).join(" OR "))
#=> Order Load (0.7ms) SELECT "orders".* FROM "orders" WHERE ("orders"."uuid" IN ('5459eed8350e1b472bfee48375034103', '21313213jkads', '43ujrefdk2384us') OR "orders"."id" IN (2, 3, 4))
更多信息:OR queries with arrays as arguments in Rails 4。
Order.where(query.where_values.inject(:or))
一直使用 arel。
MetaWhere 插件非常棒。
轻松混合 OR 和 AND,加入任何关联的条件,甚至指定 OUTER JOIN!
Post.where({sharing_level: Post::Sharing[:everyone]} | ({sharing_level: Post::Sharing[:friends]} & {user: {followers: current_user} }).joins(:user.outer => :followers.outer}
只需在条件中添加 OR
Model.find(:all, :conditions => ["column = ? OR other_column = ?",value, other_value])
你可以这样做:
Person.where("name = ? OR age = ?", 'Pearl', 24)
或更优雅,安装 rails_or gem 并执行以下操作:
Person.where(:name => 'Pearl').or(:age => 24)
我刚刚从客户工作中提取了 this plugin,它允许您将范围与 .or.
结合起来,例如。 Post.published.or.authored_by(current_user)
。 Squeel(MetaSearch 的较新实现)也很棒,但不允许您使用 OR 范围,因此查询逻辑可能会有点多余。
使用 rails + arel,更清晰的方法:
# Table name: messages
#
# sender_id: integer
# recipient_id: integer
# content: text
class Message < ActiveRecord::Base
scope :by_participant, ->(user_id) do
left = arel_table[:sender_id].eq(user_id)
right = arel_table[:recipient_id].eq(user_id)
where(Arel::Nodes::Or.new(left, right))
end
end
产生:
$ Message.by_participant(User.first.id).to_sql
=> SELECT `messages`.*
FROM `messages`
WHERE `messages`.`sender_id` = 1
OR `messages`.`recipient_id` = 1
Book.where.any_of(Book.where(:author => 'Poe'), Book.where(:author => 'Hemingway')
我想补充一下,这是一种搜索 ActiveRecord 的多个属性的解决方案。自从
.where(A: param[:A], B: param[:B])
将搜索 A 和 B。