[RUBY-ON-RAILS] 액티브 Arel OR 조건
RUBY-ON-RAILS액티브 Arel OR 조건
당신은 어떻게 논리적 OR 대신 AND 사용이 개 다른 조건을 결합 할 수 있습니다?
참고 :이 조건은 레일 범위로 생성하고 쉽게 경우 ( "X 또는 Y")와 같은 무언가로 변경할 수 없습니다 직접.
간단한 예 :
admins = User.where(:kind => :admin)
authors = User.where(:kind => :author)
그것은 (이 특정 경우에 의미가있는) 적용 및 조건을 쉽게 :
(admins.merge authors).to_sql
#=> select ... from ... where kind = 'admin' AND kind = 'author'
그러나 당신은 어떻게 이미 2 개 개의 다른 Arel 관계를 갖는 다음 쿼리를 생성 할 수 있습니다?
#=> select ... from ... where kind = 'admin' OR kind = 'author'
그것은 (Arel의 추가 정보에 따라) 같다 :
그러나 나는 여기에 적용하고 뭔가를 작성하는 기대하지 않는다 희망한다 :
(admins.or authors).to_sql
해결법
-
==============================
1.나는 파티에 조금 늦게 해요,하지만 여기에 내가 가지고 올 수있는 최선의 제안이다 :
나는 파티에 조금 늦게 해요,하지만 여기에 내가 가지고 올 수있는 최선의 제안이다 :
admins = User.where(:kind => :admin) authors = User.where(:kind => :author) admins = admins.where_values.reduce(:and) authors = authors.where_values.reduce(:and) User.where(admins.or(authors)).to_sql # => "SELECT \"users\".* FROM \"users\" WHERE ((\"users\".\"kind\" = 'admin' OR \"users\".\"kind\" = 'author'))"
-
==============================
2.액티브 쿼리 액티브 :: 관계 객체 (강합니다 지원하거나하지 않는)이며,하지 (할) 객체를 Arel.
액티브 쿼리 액티브 :: 관계 객체 (강합니다 지원하거나하지 않는)이며,하지 (할) 객체를 Arel.
[UPDATE는 : 레일 5에서, "또는"액티브지지된다 : 관계; https://stackoverflow.com/a/33248299/190135 참조]
그러나 다행히도, 그 곳 방법은 ARel 쿼리 개체를 받아들입니다. 사용자 <액티브 :: 자료 그렇다면 ...
users = User.arel_table query = User.where(users[:kind].eq('admin').or(users[:kind].eq('author')))
query.to_sql 이제 안심을 보여줍니다
SELECT "users".* FROM "users" WHERE (("users"."kind" = 'admin' OR "users"."kind" = 'author'))
명확하게하기 위해, 당신은 몇 가지 일시적인 부분 쿼리 변수를 추출 할 수 있습니다 :
users = User.arel_table admin = users[:kind].eq('admin') author = users[:kind].eq('author') query = User.where(admin.or(author))
쿼리가 일단 자연적으로, 당신은 실제 데이터베이스 호출을 실행하는 query.all 사용할 수 있습니다.
-
==============================
3.실제 arel 페이지에서 :
실제 arel 페이지에서 :
-
==============================
4.레일 5으로서 우리는이 작업을 수행 할 수 있도록 액티브 :: 관계 #이 있거나 :
레일 5으로서 우리는이 작업을 수행 할 수 있도록 액티브 :: 관계 #이 있거나 :
User.where(kind: :author).or(User.where(kind: :admin))
... 당신이 기대할 SQL로 변환됩니다되는 :
>> puts User.where(kind: :author).or(User.where(kind: :admin)).to_sql SELECT "users".* FROM "users" WHERE ("users"."kind" = 'author' OR "users"."kind" = 'admin')
-
==============================
5.나는 mongoid의 #any_of에 액티브 대안을 찾고 같은 문제에 충돌했습니다.
나는 mongoid의 #any_of에 액티브 대안을 찾고 같은 문제에 충돌했습니다.
@jswanner의 대답은 좋지만, 어디에서 매개 변수가 해시 경우에만 작동합니다 :
> User.where( email: 'foo', first_name: 'bar' ).where_values.reduce( :and ).method( :or ) => #<Method: Arel::Nodes::And(Arel::Nodes::Node)#or> > User.where( "email = 'foo' and first_name = 'bar'" ).where_values.reduce( :and ).method( :or ) NameError: undefined method `or' for class `String'
두 문자열과 해시를 사용할 수있게하려면이 사용할 수 있습니다 :
q1 = User.where( "email = 'foo'" ) q2 = User.where( email: 'bar' ) User.where( q1.arel.constraints.reduce( :and ).or( q2.arel.constraints.reduce( :and ) ) )
사실, 그것은 추한, 당신은 매일하는 것이 사용하지 않습니다. 여기에 내가 만든 한 일부 #any_of 구현은 다음과 같습니다 https://gist.github.com/oelmekki/5396826
그것은 그렇게 할 수 있습니다 :
> q1 = User.where( email: 'foo1' ); true => true > q2 = User.where( "email = 'bar1'" ); true => true > User.any_of( q1, q2, { email: 'foo2' }, "email = 'bar2'" ) User Load (1.2ms) SELECT "users".* FROM "users" WHERE (((("users"."email" = 'foo1' OR (email = 'bar1')) OR "users"."email" = 'foo2') OR (email = 'bar2')))
편집 : 그 이후로, 나는 도움 건물 또는 쿼리에 보석을 발표했습니다.
-
==============================
6.그냥 OR 조건에 대한 범위를합니다
그냥 OR 조건에 대한 범위를합니다
scope :author_or_admin, where(['kind = ? OR kind = ?', 'Author', 'Admin'])
-
==============================
7.그것은 다음과 같이 뭔가 것 SmartTuple 사용 :
그것은 다음과 같이 뭔가 것 SmartTuple 사용 :
tup = SmartTuple.new(" OR ") tup << {:kind => "admin"} tup << {:kind => "author"} User.where(tup.compile)
또는
User.where((SmartTuple.new(" OR ") + {:kind => "admin"} + {:kind => "author"}).compile)
당신은 내가 바이어스라고 생각 할 수 있습니다,하지만, 난 여전히 훨씬 더 명확하고이 특정 경우에 체인 방법보다 편리되는 전통적인 데이터 구조 작업을 고려하십시오.
-
==============================
8.(멋진 솔루션이 실제로 어느 날 도움) jswanner 답변을 확장 사람들을 인터넷 검색을위한하려면 :
(멋진 솔루션이 실제로 어느 날 도움) jswanner 답변을 확장 사람들을 인터넷 검색을위한하려면 :
이 같은 범위를 적용 할 수 있습니다
scope :with_owner_ids_or_global, lambda{ |owner_class, *ids| with_ids = where(owner_id: ids.flatten).where_values.reduce(:and) with_glob = where(owner_id: nil).where_values.reduce(:and) where(owner_type: owner_class.model_name).where(with_ids.or( with_glob )) } User.with_owner_ids_or_global(Developer, 1, 2) # => ...WHERE `users`.`owner_type` = 'Developer' AND ((`users`.`owner_id` IN (1, 2) OR `users`.`owner_id` IS NULL))
-
==============================
9.이 방법에 대한 어떤 : http://guides.rubyonrails.org/active_record_querying.html#hash-conditions (그리고 2.3.3 확인)
이 방법에 대한 어떤 : http://guides.rubyonrails.org/active_record_querying.html#hash-conditions (그리고 2.3.3 확인)
admins_or_authors = User.where(:kind => [:admin, :author])
-
==============================
10.우리가 여기에 해킹 할 필요가 불행하게도 그것은 기본적으로 지원되지 않습니다.
우리가 여기에 해킹 할 필요가 불행하게도 그것은 기본적으로 지원되지 않습니다.
그리고 꽤 비효율적 인 SQL (희망 DBA가 그것을보고하지 않는 :-))는이 같은 해킹 외모 :
admins = User.where(:kind => :admin) authors = User.where(:kind => :author) both = User.where("users.id in (#{admins.select(:id)}) OR users.id in (#{authors.select(:id)})") both.to_sql # => where users.id in (select id from...) OR users.id in (select id from)
이 subselets를 생성합니다.
그리고 조금 더 나은 같은 외모 (SQL의 관점에서) 해킹 :
admins_sql = admins.arel.where_sql.sub(/^WHERE/i,'') authors_sql = authors.arel.where_sql.sub(/^WHERE/i,'') both = User.where("(#{admins_sql}) OR (#{authors_sql})") both.to_sql # => where <admins where conditions> OR <authors where conditions>
이것은 적절한 OR 조건을 생성하지만 분명히 그것은 단지 계정으로 범위의 WHERE 참여한다.
내가 그것을 어떻게 수행을 볼 때까지 나는 1 일을 선택했다.
어떤 경우에는, 당신은 꽤 조심하고 생성 된 SQL을보고해야합니다.
from https://stackoverflow.com/questions/7976358/activerecord-arel-or-condition by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] 레일 오류에 루비를 처리하는 방법 : " '보석 액티브 - PostgreSQL의 어댑터를 설치`PostgreSQL의 어댑터를 설치하십시오" (0) | 2020.02.08 |
---|---|
[RUBY-ON-RAILS] 어떻게 레일 URL 헬퍼에 대한 기본 호스트를 설정합니까? (0) | 2020.02.08 |
[RUBY-ON-RAILS] 단지 다시로드 한 후 작동 자바 스크립트 레일 (0) | 2020.02.08 |
[RUBY-ON-RAILS] AngularJS와 : 숫자 만 텍스트 상자에 입력 할 수 있습니다 (0) | 2020.02.08 |
[RUBY-ON-RAILS] TZInfo :: DataSourceNotFound 오류 Windows에서 레일 v4.1.0 서버 시작 (0) | 2020.02.08 |