You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails:如何在原生SQL查询的Scope中添加Where子句?

解决Submission模型trending Scope的过滤与排序问题

正确实现代码

根据你的需求,结合Ahoy::Event的统计逻辑,以下是正确的trending Scope实现:

class Submission < ApplicationRecord
  belongs_to :contest

  scope :trending, ->(time_range, contest_id) {
    # 统计指定时间范围内每个投稿的浏览量
    event_stats = Ahoy::Event
      .where(name: 'view_submission') # 替换为你实际的浏览事件名称
      .where(time: time_range)
      .group("properties->>'submission_id'") # 假设投稿ID存储在event的properties中
      .select("properties->>'submission_id' AS submission_id, COUNT(*) AS view_count")

    # 左连接统计结果,确保无浏览量的投稿也能被返回
    joins("LEFT JOIN (#{event_stats.to_sql}) AS event_counts ON event_counts.submission_id = submissions.id::text")
      .where(contest_id: contest_id) # 在主表过滤指定竞赛的投稿
      .select("submissions.*, COALESCE(event_counts.view_count, 0) AS view_count") # 用COALESCE将NULL转为0
      .order("view_count DESC") # 按浏览量降序排序
  }
end

多态关联适配(如果使用)

如果Ahoy事件通过多态关联绑定Submission,直接用subject_id和subject_type更安全:

scope :trending, ->(time_range, contest_id) {
  event_stats = Ahoy::Event
    .where(name: 'view_submission')
    .where(time: time_range)
    .where(subject_type: 'Submission')
    .group(:subject_id)
    .select("subject_id AS submission_id, COUNT(*) AS view_count")

  joins("LEFT JOIN (#{event_stats.to_sql}) AS event_counts ON event_counts.submission_id = submissions.id")
    .where(contest_id: contest_id)
    .select("submissions.*, COALESCE(event_counts.view_count, 0) AS view_count")
    .order("view_count DESC")
}

你之前的问题原因

  1. 结果不全:

    • 之前默认用内连接(INNER JOIN)会过滤掉无浏览记录的投稿,改用LEFT JOIN可保留所有符合竞赛条件的投稿,即使浏览量为0。
    • 若把where(contest_id: contest_id)加在子查询中,Ahoy::Event表本身无contest_id字段,属于无效过滤,必须在主表submissions上做过滤。
  2. 排序异常:

    • 未显式指定按统计出的view_count降序排序,或排序字段指向错误列。
    • 用COALESCE把NULL转为0,确保无浏览量的投稿能正确排在末尾。
  3. SQL语法错误:

    • 直接在select语句中嵌入WHERE(contest_id = #{contest_id})属于语法错误,同时存在SQL注入风险,绝对不能用字符串拼接处理参数,应使用ActiveRecord参数化查询或正确的子查询拼接方式。

调用方式

和你期望的一致:

@submissions = Submission.trending(30.days.ago..Time.zone.now, @contest.id)

内容的提问来源于stack exchange,提问作者yellowreign

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:05:30