问题描述
我的rails应用程序中有一个音频模型,该模型使用id
和parent_audio_id字段构建层次结构。单个音频可以是另一个音频的子音频,也可以有多个子音频(我称其为衍生音频)。
我已经引用了this edge guide on self joins to construct the relationships,and this SO post to help troubleshoot
使用下面的活动记录查询,我得到了一个数据集,其中父音频数据重复了N次,其中N等于该父级的子记录数。
在给定自连接关系的情况下,如何返回给定父音频记录的子记录?
**Audio.rb**
class Audio < ApplicationRecord
has_many :derivatives,:class_name => "Audio",:foreign_key => "parent_audio_id"
belongs_to :parent_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
添加到查询中。它不会选择联接表上的任何列,并且不会返回关联。它会根据调用的内容返回一个新的作用域-因此,在这种情况下,作用域将选择在联接表中至少具有一个匹配项的音频(至少一个后代)。
.joins
主要用于基于联接表过滤记录:
Patient.joins(:appointments)
.where(scheduled_at: Time.current..)
或选择聚合:
Hotel.joins(:reviews)
.select('hotels.*','AVG(reviews.rating) AS average_rating')
.group(:id)
如果要返回特定Audio的后代,则需要在该类的实例上调用由关联宏生成的方法:
@audio = Audio.find(params[:id])
@descendents = @audio.descendents
ActiveRecord将自动创建一个单独的查询来加载后代。
您可以使用.eager_load
强制执行单个查询,而不是两个查询:
@audio = Audio.eager_load(:descendents)
.find(params[:id])
@descendents = @audio.descendents