如何筛选数据库查询以不包含基于关联表的记录?



我有一个用户模型,用户可以对其他用户进行评分。他们通过与名为 rating 的表进行多对多关联来实现这一点,该表具有与 user_id 对应的rater_id和ratee_id字段(用户上的多对多自联接)。这些模型是:

# app/models/user.rb
has_many :ratings_as_rater, class_name: "Rating", foreign_key: "rater_id"
has_many :ratings_as_ratee, class_name: "Rating", foreign_key: "ratee_id"
# app/models/rating.rb
belongs_to :rater, class_name: "User"
belongs_to :ratee, class_name: "User"

评级表上有一个复合指数:

# db/schema.rb
create_table "ratings", force: :cascade do |t|
t.integer "rater_id"
t.integer "ratee_id"
t.integer "rate" # Users rated on scale 1-4
t.index ["ratee_id"], name: "index_ratings_on_ratee_id"
t.index ["rater_id"], name: "index_ratings_on_rater_id"
t.index ["rater_id", "ratee_id"], name: "index_ratings_on_rater_id_and_ratee_id", unique: true
end

在用户索引页面上,我只想显示current_user尚未评级的用户。所以在users_controller而不是:

def index
@users = User.all
end

如何仅显示current_user尚未评级的用户?Current_user ID 存储在会话 Cookie 中。

如果您设置间接关联,则非常简单:

class User < ApplicationRecord
has_many :ratings_as_rater, class_name: "Rating", foreign_key: "rater_id"
has_many :ratings_as_ratee, class_name: "Rating", foreign_key: "ratee_id"
has_many :raters, through: :ratings_as_ratee,
source: :rater
has_many :rated_users, through: :ratings_as_rater,
source: :ratee
# class level scope to fetch users with no rating
def self.unrated_users
left_outer_joins(:ratings_as_rater).where(ratings: { id: nil })
end
# users not rated by this user
def unrated_users
self.class.where.not(id: self.rated_users)
end
end

一个重要的性能方面是做User.where.not(id: self.rated_users)而不是User.where.not(id: self.rated_users.ids).这允许 ActiveRecord 构造一个子选择,而不是将 id 从数据库拉出到 Ruby 中,然后将它们放回一个超长查询中。

最新更新