简体   繁体   中英

Rails 5: Query which excludes results if they're associated with a specific record

I've got two models: Playlist and Item . I want to build a query which returns all playlists except those which have an specific item.

These are the models:

class Playlist < ApplicationRecord
  has_many :items
end

class Item < ApplicationRecord
  belongs_to :playlist
end

This is a query which doesn't work since there could be playlists which have the specified item, but also several more, and if they have other items, they are included (which is what I don't want):

Playlist.left_outer_joins(:items).where.not(items: { uid: id })

For the record, my DBMS is PostgreSQL 9.6

Probably this can be written in a better way but it should work:

join_sql = Arel.sql(
  "LEFT OUTER JOIN items ON " \
  "(items.playlist_id = playlists.uid " \
  "AND items.some_id = '#{item.some_id}')"
)

Playlist.where(owner: owner)
        .joins(join_sql)
        .where(items: { playlist_id: nil })

The concept is similar to this one: https://stackoverflow.com/a/2686266

I don't have a setup to quickly test this, but I think you can use a Rails ActiveRecord subquery:

Playlist.where.not(id: Item.select(:pl_id).where(id: id_to_exclude))

Here, pl_id is the name of the attribute in Item corresponding to the playlist Id. I'm also assuming that id is the primary key in each of your tables. This might be a compact way for a result, but may not be the most efficient from a query perspective.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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