2009-07-08 1 views
3

HABTM과 연결된 두 모델이 있습니다. 실제로는 양단에서 has_many : through를 조인 테이블과 함께 사용합니다. 두 ModelB 중 두 모델과 관련된 ModelA를 모두 가져와야합니다. ModelB_1에 대한 모든 ModelAs가 ModelB_2에 대한 모든 ModelAs와 연결되는 것을 원하지 않습니다. 나는 ModelB_1과 ModelB_2 모두와 관련된 모든 ModelAs를 원합니다. 2 개의 ModelB에만 국한되지 않고 최대 50 개의 ModelB가 될 수 있으므로 확장해야합니다.HABTM은 "AND"조인이 아닌 "OR"조인트로 찾습니다.

* Find all books that were written by all 3 authors together. 
* Find all movies that had the following 4 actors in them. 
* Find all blog posts that belonged to BOTH the Rails and Ruby categories for each post. 
* Find all users that had all 5 of the following tags: funny, thirsty, smart, thoughtful, and quick. (silly example!) 
* Find all people that have worked in both San Francisco AND San Jose AND New York AND Paris in their lifetimes. 

나는 이러한 목표를 달성하기 위해 다양한 방법을 생각했지만, 그들은 ':

내가 더 나은 생각, 비유의 다양한 사용하여 문제를 설명 할 수는 이전 단락보다 내 문제를 설명 총체적으로 비효율적이고 매우 frowned.

위의 비유를 사용하여 마지막 도시에서 각 도시의 모든 사람들에 대한 쿼리를 수행 한 다음 각 배열에서 각 배열에있는 항목을 찾을 수 있습니다. 그건 최소 5 쿼리, 그 쿼리의 모든 데이터는 애플 리케이션으로 다시 전송, 다음 응용 프로그램이 집중적으로 서로 5 개의 배열을 비교해야합니다 (루프 풍부한!). 그건 역 겹네, 그렇지?

또 다른 가능한 해결책은 검색 결과를 서로 겹치게하는 것인데, 기본적으로 위와 동일하지만 여러 쿼리와 처리가 제거되지는 않습니다. 또한, 사용자가 50 개의 옵션을 가질 수있는 확인란이나 값을 제출 한 경우 체인을 어떻게 동적으로 만들겠습니까? 더러운 것 같습니다. 루프가 필요할 것입니다. 또한 검색 기간이 길어질 수 있습니다.

분명히 가능하면 우리는 데이터베이스에서이 작업을 수행하도록하고 싶습니다. 사람들이 여러 조건을 넣으라고 제안했습니다. 불행히도 일반적으로 HABTM을 사용한 OR 만 수행 할 수 있습니다.

내가 건너 뛰는 또 다른 해결책은 스핑크스 또는 UltraSphinx와 같은 검색 엔진을 사용하는 것입니다. 내 특별한 상황에 대해, 나는 이것이 잔인하다고 생각하며, 나는 그것을 피하려고한다. 여전히 사용자가 임의의 수의 ModelB에 대한 쿼리를 작성하고 모든 ModelA를 찾을 수있는 솔루션이 있어야한다고 생각합니다.

이 문제를 어떻게 해결하겠습니까?

+0

나는 이것을 수행하는 데 도움이되는 사용자 지정 쿼리에서 JOIN 및 GROUP을 사용하는 방법을 특히 좋아합니다. SQL 창의력을 환영합니다! –

답변

4

이 작업을 수행 할 수 있습니다

  1. 즉 가하고, (결합 모델을 통해) ModelB에 합류 당신이 찾고있는 값 중 하나를 가지고있는 ModelBs를 필터링하여 MODELA에서 쿼리를 작성 OR에있는 그들 (ie where ModelB = 'ModelB_1' or ModelB = 'ModelB_2'). 이 쿼리를 사용하면 결과 집합에 여러 ModelA 행이 있으며 각 ModelB 조건에 정확히 하나의 행이이됩니다.

  2. 필요한 ModelA 열 (원하는 경우 모두 포함)의 쿼리에 조건별로 그룹을 추가하십시오. 각 행에 대한 수 ()는 만족 된 ModelB 조건 수 *와 같습니다.

  3. count(*) ModelB 조건의 수와 동일하면 만족

예 있어야 행만 선택하는 '갖는'상태 추가

model_bs_to_find = [100, 200] 
ModelA.all(:joins=>{:model_a_to_b=>:model_bs}, 
      :group=>"model_as.id", 
      :select=>"model_as.*", 
      :conditions=>["model_bs.id in (?)", model_bs_to_find], 
      :having=>"count(*)=#{model_bs_to_find.size}") 

을 N.B.그런 식으로 지정된 group 및 select 매개 변수가 MySQL에서 작동하므로 표준 SQL 방법은 group_as 열의 전체 목록을 group 및 select 매개 변수에 모두 넣는 것입니다.

+0

놀라운! 그것은 위대한 작품. SQL 쿼리에 GROUP BY 및 HAVING을이 방식으로 추가하면 완벽하게 작동합니다. 잠시 후에 위에서 설명한 Ruby 방식을 테스트 할 것입니다. –

+0

모델 참조에 기호를 사용하지 않고 : joins 문에서 조인 테이블을 참조 할 수있는 방법이 있습니까? 내 조인 테이블은 데이터베이스에 있지만 모델이 아닙니다 (이후 has_many : through 대신 HABTM을 사용하기 때문에). –

+0

: 조인 => : model_bs가 잘 작동하는 것처럼 보였습니다! –

관련 문제