jsonb 列上的活动记录请求并加入 table

Active record request on jsonb column and join table

我正在尝试使用 jsonb 字段和与程序的关联对 table 执行查询:

  create_table "sessions", force: :cascade do |t|
    t.jsonb "lms_data", default: "{}", null: false
    t.bigint "program_id"

lms_data 字段有一个 endDate 键,在我的会话模型中我已经有一个 future_end_date 范围:

  scope :future_end_date, -> { where('(lms_data::jsonb->> ?) > ?', 'endDate', Time.now) }

我知道要执行一个查询:

我试过了:

 Session
        .future_end_date
        .joins(:program)
        .group('programs.title')

但这引发了:

ActiveRecord::StatementInvalid - PG::AmbiguousColumn: ERROR:  column reference "lms_data" is ambiguous
LINE 1: ...gram_id" WHERE "sessions"."account_id" =  AND ((lms_data::...

您能解释一下为什么会出现此错误以及如何执行所需的查询吗? (在我粘贴的错误消息中有 WHERE "sessions"."account_id" 因为这是一个多租户应用程序,默认情况下所有查询都在帐户租户模型范围内)

--- 编辑两个模型的架构 ---

Session :
  create_table "sessions", force: :cascade do |t|
    t.jsonb "lms_data", default: "{}", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.bigint "program_id"
    t.bigint "account_id"
    t.index ["account_id"], name: "index_sessions_on_account_id"
    t.index ["lms_data"], name: "index_sessions_on_lms_data", using: :gin
    t.index ["program_id"], name: "index_sessions_on_program_id"
  end

  create_table "programs", force: :cascade do |t|
    t.string "title"
    t.string "headline"
    t.text "description"
    t.integer "duration_in_hours"
    t.bigint "category_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.boolean "featured"
    t.jsonb "lms_data", default: "{}", null: false
    t.bigint "author_id"
    t.string "dpc_number"
    t.integer "position"
    t.text "goals"
    t.string "publication_status", default: "draft"
    t.date "upcoming_date"
    t.string "session_subscription_mode", default: "sliding"
    t.integer "program_recommandation_id"
    t.bigint "account_id"
    t.index ["account_id"], name: "index_programs_on_account_id"
    t.index ["author_id"], name: "index_programs_on_author_id"
    t.index ["category_id"], name: "index_programs_on_category_id"
    t.index ["lms_data"], name: "index_programs_on_lms_data", using: :gin
    t.index ["program_recommandation_id"], name: "index_programs_on_program_recommandation_id"
  end

你在两个 table 中都有一个 lms_data 你正在使用 sessionsprograms,所以当执行查询时它不知道是哪一列属于什么table。举个例子:

WITH tmp(id, lms_data)  AS (values (1, NULL), (2, NULL)),
     tmp2(id, lms_data) AS (values (1, NULL))
SELECT lms_data
FROM tmp t1 INNER JOIN tmp2 t2 ON t1.id = t2.id;
-- ERROR:  column reference "lms_data" is ambiguous
-- LINE 1: ..., tmp2(id, lms_data) as (values (1, NULL)) select lms_data f...

两个 tables,都具有相同的 lms_data 列,JOIN 工作正常,但 SELECT 语句抛出与现在相同的错误。

您可以在 table 名称前加上前缀以避免出现这种情况:

scope :future_end_date, -> { where('(sessions.lms_data::jsonb->> ?) > ?', 'endDate', Time.now) }

请注意,您可以使用 CURRENT_TIMESTAMP 函数而不是在作用域中绑定常量值 (Time.now):

(sessions.lms_data::jsonb->> ?) > CURRENT_TIMESTAMP