0

ジャンルの映画データベースがあり、特定のジャンルを除くすべての映画を表示したいとしましょう。私はすべての関連付けをセットアップし、問題なく動作しています。

これを行うために、Squeelという名前の gem に出会い、このコードを書きました。

movies = Movie.joins(:movie_genres).approved

# This is just an array of id's
included_genres = params[:genres][:included_genres]
excluded_genres = params[:genres][:excluded_genres]

if included_genres

  # This works just fine
  movies = movies.where(movie_genres: {genre_id: included_genres})

  # This works too but IMO MySQL IN operator is faster.
  #movies = movies.where{movie_genres.genre_id.eq_any included_genres}

end

if excluded_genres

  # Here is where the problems occurs, it generates perfectly nice SQL 
  # but for some reason it doesn't work as expected.
  movies = movies.where{movie_genres.genre_id.not_eq_any excluded_genres}

  # If we do it this way, it will only not match those movies 
  # that have all the selected genres at once, i need to match 
  # all movies that have atleast one of the inputted genres
  #movies = movies.where("genre_id NOT IN (?)", excluded_genres)
  #movies = movies.where{movie_genres.genre_id.not_eq_all excluded_genres}    

end

movies = movies.group(:id)

ええ、Squeel のおかげで、次の SQL を取得できます。

SELECT `movies`.* FROM `movies` 
INNER JOIN `movie_genres` ON `movie_genres`.`movie_id` = `movies`.`id` 
WHERE ((`movie_genres`.`genre_id` != 10 OR `movie_genres`.`genre_id` != 12)) 
GROUP BY `movies`.`id`;

期待どおりに機能するため、ジャンルは含まれていません。

その結果、 where 条件は、それがある場合とない場合に違いが見られないため、適用されないように見えます。

スクリーンショットを参照してください: SQLクエリの作業を示すMysqlターミナル出力

なぜそれが機能しないのか、どこから掘り始めるべきなのか、誰にもアイデアはありますか?

すべての助けに感謝します。

4

2 に答える 2

1

問題は、SQLではなくロジックにあります。「OR」ロジックを使用すると、任意の条件を満たす行を取得することが期待されるため、クエリでは、10!=12であるためID10の行を取得します。WHEREINの使用-細かい方法

于 2012-12-30T22:58:22.033 に答える
0

名前付きスコープを使用してこの問題を解決しました

scope :excluding_genres, 
  lambda { |genres| { 
    :conditions => 
       ['movies.id NOT IN 
       (SELECT movies.id FROM movies 
        LEFT JOIN movie_genres ON movies.id = movie_genres.movie_id 
        WHERE movie_genres.genre_id IN (?))', genres] 
  }}
于 2012-12-30T22:35:33.947 に答える