获取没有任何特定视频的视频

时间:2016-08-31 11:53:57

标签: ruby-on-rails associations

我正在尝试使用这些参数获取所有视频。但即使我没有得到任何错误,我仍然会得到一些类别[17]的视频。

  • 没有任何遗漏类别[15,17,26,32,35,36,37]
  • 的持续时间超过100
  • 他们是独一无二的

Video.rb

class Video < ActiveRecord::Base
   self.primary_key = "id"
   has_and_belongs_to_many :categories
end

Category.rb

class Category < ActiveRecord::Base
    has_and_belongs_to_many :videos
end

我的查询

    @excluded_categories = [15,17,26,32,35,36,37]

    @videos = Video.joins(:categories).where("duration >= 100").where.not( categories: { id: @excluded_categories } ).pluck(:video_id).uniq

有没有更好的方法来编写如何编写此查询?

1 个答案:

答案 0 :(得分:0)

This is a very common SQL case: "fetch a list of object which don't have a certain relation".

The only solution in these cases is to transform the sentence in "fetch the list of objects which are not in the list of objects with a certain relation".

In you case you have to extract all the videos whch are not included in the list of videos with one of these categories.

In SQL:

select videos.*
from videos
where videos.id not in ( select v2.id
                         from videos v2
                         join categories_videos cv on cv.video_id == v2.id
                         join categories c on cv.category_id == c.id
                         where c.id in '15,17,26,32,35,36,37' )

Converted into ActiveRecord you will have:

class Video < ActiveRecord::Base
  self.primary_key = :id
  has_and_belongs_to_many :categories
  scope with_categories: ->(ids) { joins(:categories).where(categories: {id: ids}) }

  scope without_categories: ->(ids) { where.not(id: with_categories(ids) }
end

so in the end...

@excluded_categories = [15,17,26,32,35,36,37]
@videos = Video.without_categories(@excluded_categories)

P.S.

Your example has an issue since doesn't retrieve videos which don't have any category.