You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Realm中创建对象引用的正确方法 健身应用数据关联问询

最优实现方案

优先采用Realm原生的对象关联关系替代当前逗号分隔ID字符串的存储方案,既可以大幅简化查询代码,还能利用Realm本身的查询优化提升读取性能,适配你后续的数据筛选需求。


步骤1:调整数据模型

将原来存储关联ID的String类型字段替换为Realm内置的List类型,直接存储关联对象的引用,无需自行维护ID映射逻辑:

// 器材类示例,确保你的现有Equipment/Muscle类符合Realm模型规范
class Equipment: Object {
    @Persisted(primaryKey: true) var id: Int = 0
    @Persisted var name: String = ""
    // 可选:添加反向关联,可快速查询某器材对应的所有动作
    @Persisted(originProperty: "equipments") var linkedExercises: LinkingObjects<Exercise>
}

class Muscle: Object {
    @Persisted(primaryKey: true) var id: Int = 0
    @Persisted var name: String = ""
    // 可选:反向关联,查询某肌肉对应的所有动作
    @Persisted(originProperty: "muscles") var linkedExercises: LinkingObjects<Exercise>
}

// 改造后的Exercise主类
class Exercise: Object {
    @Persisted(primaryKey: true) var exerciseID: Int = 0
    @Persisted var name: String = ""
    @Persisted var category: Int
    // 替换原String字段,直接存储关联对象集合
    @Persisted var equipments: List<Equipment>
    @Persisted var muscles: List<Muscle>
    @Persisted var instruction: String
    @Persisted var gif: String?
    @Persisted var image: String? = nil
    
    convenience init(
        name: String, 
        category: Int, 
        equipments: [Equipment], 
        muscles: [Muscle],
        instruction: String, 
        gif: String?, 
        image: String?
    ) {
        self.init()
        self.name = name
        self.category = category
        self.equipments.append(objectsIn: equipments)
        self.muscles.append(objectsIn: muscles)
        self.instruction = instruction
        self.gif = gif
        self.image = image
    }
}

因为你的初始数据是预置的,只需要在制作预置Realm文件时直接写入关联关系即可,首次启动替换默认Realm文件的逻辑无需修改。


步骤2:简化查询逻辑

改造后无需再做字符串拆分、ID转换、单独查询关联对象的操作,可直接读取关联属性:

// 直接持有Realm的Results集合,自动同步数据
var exercises: Results<Exercise>?

func getAllExercises() {
    exercises = RealmService.shared.realm.objects(Exercise.self)
    
    // 示例:获取所有动作关联的全部器材,自动去重
    let allEquipments = Array(Set(exercises?.flatMap(\.equipments) ?? []))
    // 示例:获取第一个动作的所有关联肌肉
    let firstMuscles = exercises?.first?.muscles
}

关联筛选也可以直接用Realm的原生查询语法实现,比如筛选所有需要哑铃(器材ID=1)且练胸肌(肌肉ID=2)的动作:

let targetExercises = RealmService.shared.realm.objects(Exercise.self)
    .filter("equipments.id == 1 AND muscles.id == 2")

关于「存值还是存引用」的选择

  • 若你的器材、肌肉数据永远不会变更,也不需要做反向查询、关联筛选,可简化为直接存储List<String>类型的器材/肌肉名称,比你当前存逗号分隔字符串的方案更简洁,也无需额外维护关联类
  • 若后续可能给器材/肌肉新增属性(比如器材图标、肌肉示意图)、需要做灵活的关联筛选,优先选择对象引用方案,扩展性和查询效率更高

内容的提问来源于stack exchange,提问作者TeddyKen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:54:03