【问题标题】:Filter a Realm list inside objects过滤对象内的领域列表
【发布时间】:2019-09-18 12:39:57
【问题描述】:

假设我在Realm 中有以下对象:

class Student: Object{
    @objc dynamic var name: String = ""
    let subjects = List<Subject>()
}

class Subject: Object{
    @objc dynamic var name: String = "" 
    @objc dynamic var grade: String = "" // A, B, C, etc
}

我想查询学生,但我只想拥有只有 A 级的 subjects

例如,如果我在 Realm 中保存了以下内容:

Student 1, subjects = [("math", "A"), ("Science", "B")]
Student 2, subjects = [("math", "C"), ("Science", "A")]
Student 3, subjects = [("math", "B"), ("Science", "C")]

我希望学生的成绩等于 A。结果应返回以下内容:

Student 1, subjects = [("math", "A")]
Student 2, subjects = [("Science", "A")]

所以我最终得到了Student 类型的领域结果,但所有subjects 的成绩都等于A。 这在 Realm DB 中可行吗?

【问题讨论】:

标签: ios swift realm


【解决方案1】:

你不能从这里完全到达那里 - 你需要一个小的中间步骤来获得所需的输出。

首先,您可以使用 ANY 聚合函数查询列表。因此,要获得任何成绩为“A”的学生,您可以这样做。

let studentResults = realm.objects(Student.self).filter("ANY subjects.grade == 'A'")

问题在于结果是实际成绩为 A 的学生,而返回的结果是 student 对象,他们的所有成绩都在他们的列表中。

幸运的是,我们还可以将过滤器直接应用于列表。因此,我们将遍历在 studentResults 中返回的每个学生,然后过滤他们的列表属性,只针对他们收到的科目和“A”。像这样

let studentResults = realm.objects(Student.self).filter("ANY subjects.grade == 'A'")
for student in studentResults {
    let gradeAResults = student.subjects.filter("grade == 'A'")

    for grades in gradeAResults {
        print(student.name, grades.name, grades.grade)
    }
}

结果是

student 1 math A
student 2 Science A

请注意,这还会多次输出学生姓名,因为他们可能在多个科目中获得了“A”。

【讨论】:

  • 感谢@Jay 提出这个建议,但我不想重复我的结果,我的目标是使用一些满足我标准的过滤来更新 Realm 结果。 Realm 本身支持的东西
  • @MohamMadSalah 不幸的是,没有您想要的直接查询。我相信对于您的用例,我的解决方案不仅是最简单的,而且是最快的。迭代有什么问题 - 即使有数千个结果,该循环也只需要几分之一秒。
  • @MohamMadSalah 查看我的另一个答案 - 它在没有任何迭代的情况下基本上做同样的事情。
【解决方案2】:

我发布了一个单独的答案,它确实回答了这个问题,但 OP 不想要任何类型的迭代。所以这是另一种使用不同方法的可能性。

对于这种方法,我们将在每个学习的科目中添加一个引用,链接回学习该科目的学生。所以学生模型现在看起来像这样

class Subject: Object{
    @objc dynamic var name: String = ""
    @objc dynamic var grade: String = "" // A, B, C, etc
    @objc dynamic var studentRef: Student!
}

我们创建一个学生对象:

let student = Student()
student.name = "Henry"

然后是他们选修的科目,并创建他们的成绩,并返回对修读该科目的学生的参考:

let subject = Subject()
subject.name = "math"
subject.grade = "A"
subject.studentRef = student

我们要返回在任何科目上获得“A”成绩的所有学生的查询是这样的

let gradeAResults = realm.objects(Subject.self).filter("grade == 'A'")
for subject in gradeAResults {
    print(subject.name, subject.grade, subject.studentRef.name)
}

输出将是

math A Henry
Science A Pete

【讨论】:

    【解决方案3】:

    这个谓词怎么样:

    SUBQUERY(subjects, $subject, $subject.grade == 'A').@count == subjects.@count
    

    用法:

    let students = realm.objects(Student.self).filter("SUBQUERY(subjects, $subject, $subject.grade == 'A').@count == subjects.@count")
    

    它会计算A级科目的数量,然后将其与该学生的科目总数进行比较,如果相同,则表示该学生只有A级科目。

    我没有测试过,但是应该可以的。

    【讨论】:

    • 谢谢,@Vin,我试过你的,但它不会过滤主题列表,它会过滤Students
    • 好吧,我误解了你的问题。您想检索具有预过滤科目(仅 A 级科目)的学生列表,不幸的是,我认为这在 Realm 中是不可能的。
    猜你喜欢
    • 2016-09-08
    • 1970-01-01
    • 1970-01-01
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多