Realm Swift 选择与一对多关系实体中的一个字段匹配的所有值

Posted

技术标签:

【中文标题】Realm Swift 选择与一对多关系实体中的一个字段匹配的所有值【英文标题】:Realm Swift select all values which match one field in one-to-many relationship entity 【发布时间】:2017-08-18 13:32:45 【问题描述】:

我在领域 Product 和 ProductType 中有两个实体。产品与产品类型具有一对多的关系。

产品实体一对多

import Foundation
import RealmSwift

class Product: Object
    dynamic var productName = ""
    let productTypeList = List<ProductType>() 

产品类型实体

import Foundation
import RealmSwift

class ProductType: Object   
  dynamic var typeName: String = ""
  dynamic var typeLogoUrl: String = ""

我的目标是选择所有产品,其中包含 ProductType typeName,例如“Electronics”。如果有这样的一对一关系,我可以很容易地做到这一点

产品实体一对一

import Foundation
import RealmSwift

class Product:Object
    dynamic var productName = ""
    dynamic var productType : ProductType? 

查询示例

let realm = try! Realm()
let productTypeName = "Electronics"
let predicate = NSPredicate(format: "productType.typeName == %@", productTypeName)
let rmProducts = realm.objects(Product.self).filter(predicate)

任何想法如何使用一对多版本的 Product 类进行查询?

【问题讨论】:

【参考方案1】:

您可以使用子查询并检查列表中与名称匹配的 productTypes 的计数是否大于 0。

let rmProducts = realm.objects(Product.self).filter("SUBQUERY(productTypeList, $type, $type.typeName == %@).@count&gt;0",productTypeName)

我已经在以下测试集上运行了查询并得到了预期的结果:

class Product:Object
    dynamic var productName = ""
    var productTypeList = List<ProductType>()


class ProductType  : Object
    dynamic var typeName: String = ""
    dynamic var typeLogoUrl: String = ""


let types = [ProductType(value: ["typeName":"Electronics","typeLogoUrl":"url"]),ProductType(value: ["typeName":"a","typeLogoUrl":"url"]),ProductType(value: ["typeName":"Electronics","typeLogoUrl":"a"]),ProductType(value: ["typeName":"b","typeLogoUrl":"url"])]

let prod1 = Product()
prod1.productName = "a"
prod1.productTypeList = List([types[0],types[1]])
let prod2 = Product()
prod2.productName = "b"
prod2.productTypeList = List([types[3],types[1]])
let prod3 = Product()
prod3.productName = "c"
prod3.productTypeList = List([types[2],types[1]])
var prod4 = Product()
prod4.productName = "d"
prod4.productTypeList = List([types[1]])

try! realm.write 
    realm.add(types)
    realm.add([prod1,prod2,prod3,prod4])


let productTypeName = "Electronics"
let predicate = NSPredicate(format: "productType.typeName == %@", productTypeName)
let rmProducts = realm.objects(Product.self).filter("SUBQUERY(productTypeList, $type, $type.typeName == %@).@count>0",productTypeName)
print(rmProducts) //rmProducts contains prod1 and prod3 as expected

【讨论】:

【参考方案2】:

对于像这样的简单查询,您需要ANY 修饰符:

realm.objects(Product.self).filter("ANY productTypeList.typeName == %@", productTypeName)

SUBQUERY,正如另一个答案中所建议的那样,仅当您需要在每个子对象上匹配多个标准时才需要。例如,如果您想查找具有 URL 以 https:// 开头的给定类型的项目的 Products,您可以使用 SUBQUERY

realm.objects(Product.self).filter("SUBQUERY(productTypeList, $type, $type.typeName == %@ AND $type.typeLogoUrl BEGINSWITH 'https://').@count > 0", productTypeName)

【讨论】:

以上是关于Realm Swift 选择与一对多关系实体中的一个字段匹配的所有值的主要内容,如果未能解决你的问题,请参考以下文章

mysql学习之路_高级数据操作

MySQL中的关系

Swift 一对多关系

Swift - 一对多排序

4.一对多关联映射

数据库的设计