简体   繁体   English

Rails AR + Mysql-排除电影流派无法正常工作

[英]Rails AR + Mysql - Excluding movie genres doesn't work as expected

Let's say I have a movie database with genres and I would like to show all movies excluding some specific genres. 假设我有一个具有流派的电影数据库,并且我想显示所有不包括某些特定流派的电影。 I have associations all set up and working just fine. 我已经建立了所有协会,并且一切正常。

So to do this, i came across the gem named Squeel and wrote this piece of code 为此,我遇到了名为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)

So yeah, thanks to Squeel we get this SQL: 是的,感谢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`;

That's without included genres as they work as expected. 由于未按预期工作,因此未包含流派。

So in result, the where condition looks like it doesn't even apply as i see no difference with or without it. 因此,结果是,where条件看起来甚至都不适用,因为我认为使用或不使用它都没有区别。

See screenshot: 看截图: MySQL终端输出显示SQL查询的工作

Does anyone have any ideas why it doesn't works and where should i start digging? 有谁知道为什么它不起作用,我应该从哪里开始挖掘?

All help is much appreciated. 非常感谢所有帮助。

The problem, is in logic, not sql. 问题出在逻辑上,而不是sql。 With "OR" logic you expect to get lines meeting any of conditions, so for your query you will get the line with id 10, because 10 != 12. Using WHERE IN - fine way 使用“或”逻辑,您希望获得符合任何条件的行,因此对于您的查询,您将获得ID为10的行,因为10!=12。使用WHERE IN-很好的方法

Solved this problem by using named scope 通过使用命名范围解决了此问题

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] 
  }}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM