ActiveRecord OR 쿼리


181

Rails 3 ActiveRecord에서 OR 쿼리를 수행하는 방법 내가 찾은 모든 예제에는 AND 쿼리가 있습니다.

편집 : OR 방법은 Rails 5부터 사용할 수 있습니다. ActiveRecord :: QueryMethods를 참조하십시오.


7
SQL을 배우십시오. ActiveRecord를 사용하면 작업을 쉽게 수행 할 수 있지만 여전히 쿼리가 수행중인 작업을 알아야합니다. 그렇지 않으면 프로젝트가 확장되지 않을 수 있습니다. 또한 SQL을 다루지 않고도 벗어날 수 있다고 생각했는데 그것에 대해 매우 잘못했습니다.
ryan0

1
@ ryan0, 당신이 너무 옳아 요. 우리는 멋진 보석과 다른 것들을 사용할 수 있지만, 이러한 보석들이 내부에서 무엇을하고 있는지, 그리고 기본 기술이 무엇인지 알고 있어야하며, 필요할 경우 보석의 도움없이 기본 기술을 사용할 수도 있습니다. 공연. 보석은 특정 수의 사용 사례를 염두에두고 만들어 지지만 프로젝트의 사용 사례 중 하나가 다른 상황이있을 수 있습니다.
rubyprince

2
도움이 될 수 있습니다 : ActiveRecord OR query Hash notation
potashin

1
Rails 5 이후 IMHO는 그레그 올슨 버전이어야합니다.Post.where(column: 'something').or(Post.where(other: 'else'))
Philipp Claßen

6
이 질문에는 ruby-on-rails-3 태그가 있습니다. 수락 된 답변이 Rails 5에만 관련된 이유는 무엇입니까?
iNulty

답변:


109

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%'))

조금 지저분하게 느껴지지만 적어도 나는 sql을 쓰지 않습니다. Arel을 더 많이 사용해야 할 것입니다.
pho3nixf1re

55
나는 더 우아한 Sequel이 얼마나 우아한 지 믿을 수 없다
Macario

3
SQL에는 아무런 문제가 없습니다. 잘못 될 수있는 것은 SQL 문자열, 즉 SQL Injection을 작성하는 방법 입니다. 따라서 데이터베이스에 대해 실행해야하는 SQL 쿼리에 사용자 입력을 제공하기 전에 사용자 입력을 삭제해야합니다. 이것은 ORM에 의해 처리 될 것이며 , 우리가 놓치기 쉬운 에지 케이스를 처리하고 있습니다. 따라서 항상 ORM 을 사용하여 SQL 쿼리를 작성 하는 것이 좋습니다 .
rubyprince

5
Another problem with SQL is that it's not database agnostic. For example matches will produce LIKE for sqlite (case insensitive by default) and ILIKE on postgres (needs explicit case insensitive like operator).
amoebe

1
@ToniLeigh ActiveRecord는 후드 아래에서 SQL을 사용하고 있습니다. SQL 삭제를 처리하고 쿼리를 DB에 무관하게 만드는 SQL 쿼리를 작성하기위한 구문 일뿐입니다. Rails가 구문을 SQL 쿼리로 변환하는 유일한 오버 헤드입니다. 그리고 그것은 단지 밀리 초의 문제입니다. 물론 성능이 가장 우수한 SQL 쿼리를 작성하여 ActiveRecord 구문으로 변환해야합니다. SQL을 ActiveRecord 구문으로 표현할 수 없으면 일반 SQL로 이동해야합니다.
rubyprince

208

하나의 열 값에 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단일 열 에서 동등한 것을 달성해야합니다.


13
이것은 가장 깨끗한 "레일 방식"답변입니다.
koonse

10
@koonse에게 감사합니다. 정확히 'OR'쿼리는 아니지만이 상황에서 동일한 결과를 생성합니다.
deadkarma

- 당신이 할 수있는 경우 도움말 stackoverflow.com/questions/15517286/...
Pratik Bothra

80
이 방법으로 두 개의 다른 열을 사용할 수 없으므로이 솔루션은 OR을 대체하지 않습니다.
fotanus 2019

152

Rails 3에서는

Model.where("column = ? or other_column = ?", value, other_value)

이것은 또한 원시 SQL을 포함하지만 ActiveRecord에 OR 연산을 수행하는 방법이 없다고 생각합니다. 귀하의 질문은 멍청한 질문이 아닙니다.


41
원시 SQL이 있더라도이 문장은 Arel보다 훨씬 명확 해 보입니다. 아마 건조기일지도 모른다.
jibiel

6
동일한 열 이름을 가진 열을 가질 수있는 다른 테이블 조인을 체인화해야하는 경우 다음과 같이 사용해야합니다.Page.where("pages.column = ? or pages.other_column = ?", value, other_value)
rubyprince

1
그리고 쿼리가 테이블의 별칭을 지정하면 실패합니다. 그 때 아레가 빛을 발합니다.
DGM

58

업데이트 된 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 에 따르면 이 or기능은 Rails 5에서 사용할 수 있습니다

업데이트 : 기능이 Rails 5 지점으로 병합되었습니다


2
orRails 5에서 사용할 수 있지만 인수 1 개가 전달 될 것으로 예상되므로 이런 방식으로 구현할 수 없습니다. Arel 객체가 필요합니다. 허용 된 답변보기
El'Magnifico

2
orActiveRecord 의 메소드는 직접 사용하는 경우 작동하지만, 범위 내에서 사용 된 경우 체인을 연결하면 기대치를 깨뜨릴 수 있습니다.
제레미 목록

@JeremyList가 말한 것은 주목입니다. 그게 날 힘들게 했어
courtsimas


23

Rails 5에는 or방법 이 제공됩니다 . (l 잉크를 문서로 )

이 메소드는 ActiveRecord::Relation객체를 받아들 입니다. 예 :

User.where(first_name: 'James').or(User.where(last_name: 'Scott'))

14

배열을 인수로 사용하려면 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))

더 자세한 정보 레일 4 인수로 배열과 OR 쿼리 .


9
또는 이것은 : Order.where(query.where_values.inject(:or))arel을 사용하는 것입니다.
Cameron Martin

> Rails 4에서 배열을 인수로 사용하여 OR 쿼리. 유용한 링크! 감사!
Zeke Fast

7

MetaWhere의 플러그인은 완전히 놀랍습니다.

OR과 AND를 쉽게 혼합하고 모든 연관 조건을 조인하며 외부 조인을 지정할 수도 있습니다!

Post.where({sharing_level: Post::Sharing[:everyone]} | ({sharing_level: Post::Sharing[:friends]} & {user: {followers: current_user} }).joins(:user.outer => :followers.outer}

6

조건에 OR을 추가하십시오.

Model.find(:all, :conditions => ["column = ? OR other_column = ?",value, other_value])

4
이것은 Rails 2에 대한 구문이며, SQL 문자열의 적어도 일부를 작성해야합니다.
pho3nixf1re

3

방금 클라이언트 작업 에서이 플러그인 을 추출 하여 스코프와 .or.예를 들어 범위를 결합 할 수 있습니다 . Post.published.or.authored_by(current_user). Squeel (MetaSearch의 최신 구현)도 훌륭하지만 OR 범위를 허용하지 않으므로 쿼리 논리가 약간 중복 될 수 있습니다.


3

레일 + 아렐을 사용하면 더 분명한 방법입니다.

# 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

3

당신은 다음과 같이 할 수 있습니다 :

Person.where("name = ? OR age = ?", 'Pearl', 24)

또는 더 우아하면 rails_or gem을 설치 하고 다음과 같이하십시오.

Person.where(:name => 'Pearl').or(:age => 24)

-2

ActiveRecord의 여러 속성을 검색하는 솔루션입니다. 이후

.where(A: param[:A], B: param[:B])

A와 B를 검색합니다.


-4
Book.where.any_of(Book.where(:author => 'Poe'), Book.where(:author => 'Hemingway')

2
귀하의 답변에 대한 설명을 추가하십시오
kvorobiev

1
Matthew 가이 구문에 대한 지원을 추가 하는 activerecord_any_of gem을 참조하고 있다고 생각 합니다.
DannyB

2
사실이라면 @DannyB에게 감사합니다. 답은 그 맥락을 설명해야합니다.
Sebastialonso
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.