rails 中的自联接返回每个预期子行的父记录
Self join in rails is returning the parent record for each expected child row
我的 rails 应用程序中有一个音频模型,它使用 id
和 parent_audio_id 字段来构建层次结构。单个音频可以是另一个音频的子音频,或者有多个子音频(我称之为派生)。
我参考了 this edge guide on self joins to construct the relationships, and this SO post to help troubleshoot
使用下面的活动记录查询,我得到了一个父音频数据重复 N 次的数据集,其中 N 等于该父项的子记录数。
如何 return 给定自连接关系的给定父音频记录的子记录?
**Audio.rb**
class Audio < ApplicationRecord
has_many :derivatives, :class_name => "Audio", :foreign_key => "parent_audio_id"
belongs_to :parent_audio, :class_name => "Audio", optional: true
end
**Audio Migration**
class CreateAudios < ActiveRecord::Migration[6.0]
def change
create_table :audios do |t|
t.references :parent_audio, foreign_key: {to_table: :audios}
end
end
end
**Audios Controller**
def audio_details
data = []
derivatives = Audio.joins(:derivatives)
data.push(derivatives)
render json: data
end
我也试过 derivatives = Derivative.joins(:audios)
但出现以下错误:
uninitialized constant Api::V1::AudiosController::Derivative
.joins
只是将 INNER JOIN
添加到查询中。它不 select 连接 table 上的任何列,也不 return 关联。它 return 是一个新的范围,基于它被调用的任何内容 - 所以在这种情况下,范围将 select 音频在加入的 table 中至少有一个匹配项(至少一个后代) .
.joins
主要用于根据加入的table:
过滤记录
Patient.joins(:appointments)
.where(scheduled_at: Time.current..)
或select聚合:
Hotel.joins(:reviews)
.select('hotels.*', 'AVG(reviews.rating) AS average_rating')
.group(:id)
如果你想return一个特定音频的后代你需要在class的实例上调用关联宏生成的方法:
@audio = Audio.find(params[:id])
@descendents = @audio.descendents
ActiveRecord 将自动创建一个单独的查询来加载死者。
您可以使用 .eager_load
强制执行单个查询而不是两个查询:
@audio = Audio.eager_load(:descendents)
.find(params[:id])
@descendents = @audio.descendents
我的 rails 应用程序中有一个音频模型,它使用 id
和 parent_audio_id 字段来构建层次结构。单个音频可以是另一个音频的子音频,或者有多个子音频(我称之为派生)。
我参考了 this edge guide on self joins to construct the relationships, and this SO post to help troubleshoot
使用下面的活动记录查询,我得到了一个父音频数据重复 N 次的数据集,其中 N 等于该父项的子记录数。
如何 return 给定自连接关系的给定父音频记录的子记录?
**Audio.rb**
class Audio < ApplicationRecord
has_many :derivatives, :class_name => "Audio", :foreign_key => "parent_audio_id"
belongs_to :parent_audio, :class_name => "Audio", optional: true
end
**Audio Migration**
class CreateAudios < ActiveRecord::Migration[6.0]
def change
create_table :audios do |t|
t.references :parent_audio, foreign_key: {to_table: :audios}
end
end
end
**Audios Controller**
def audio_details
data = []
derivatives = Audio.joins(:derivatives)
data.push(derivatives)
render json: data
end
我也试过 derivatives = Derivative.joins(:audios)
但出现以下错误:
uninitialized constant Api::V1::AudiosController::Derivative
.joins
只是将 INNER JOIN
添加到查询中。它不 select 连接 table 上的任何列,也不 return 关联。它 return 是一个新的范围,基于它被调用的任何内容 - 所以在这种情况下,范围将 select 音频在加入的 table 中至少有一个匹配项(至少一个后代) .
.joins
主要用于根据加入的table:
Patient.joins(:appointments)
.where(scheduled_at: Time.current..)
或select聚合:
Hotel.joins(:reviews)
.select('hotels.*', 'AVG(reviews.rating) AS average_rating')
.group(:id)
如果你想return一个特定音频的后代你需要在class的实例上调用关联宏生成的方法:
@audio = Audio.find(params[:id])
@descendents = @audio.descendents
ActiveRecord 将自动创建一个单独的查询来加载死者。
您可以使用 .eager_load
强制执行单个查询而不是两个查询:
@audio = Audio.eager_load(:descendents)
.find(params[:id])
@descendents = @audio.descendents