ruby-on-rails - Rails 中的自联接正在返回每个预期子行的父记录
问题描述
我的 Rails 应用程序中有一个音频模型,它使用一个id
和 parent_audio_id 字段来构建层次结构。单个音频可以是另一个音频的子级,也可以有多个子级音频(我称之为派生类)。
我已经参考了这个关于自我连接的边缘指南来构建关系,以及这个 SO 帖子来帮助解决问题
使用下面的活动记录查询,我得到一个数据集,其中父音频数据重复了 N 次,其中 N 等于该父级的子记录数。
在给定自加入关系的情况下,如何返回给定父音频记录的子记录?
**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
只需将 a 添加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
推荐阅读
- java - 什么相当于 PHP 中的 Java 中的 preg_replace 和 base64_decode?
- c# - 在 C# 中使用 'ref' 或 'out' 常见做法
- haskell - 当我的 do 不为空时,为什么会出现“Empty do”错误?
- python - 更改文本组件的比例
- python - 如何在图像中找到数字的中心坐标
- python - 获取按 ID 分区的每个字段的非空数据
- node.js - 使用 koa-jwt 仅保护某些路由
- ios - 如何在 Realm Swift 中将一对一关系迁移到一对多关系
- c++ - C/++/ASM - 是否可以从 0x0 读取堆栈/堆大小和虚拟内存地址空间?
- android - 华为 Push Kit 错误:907135701:范围列表为空