Rails中的自我连接正在返回每个预期子行的父记录

问题描述

我的rails应用程序中有一个音频模型,该模型使用id和parent_audio_id字段构建层次结构。单个音频可以是另一个音频的子音频,也可以有多个子音频(我称其为衍生音频)。

我已经引用了this edge guide on self joins to construct the relationshipsand 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

请参见Rails Guides: Active Record Query Interface