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

时间:2017-08-18 13:32:46

标签: swift swift3 realm nspredicate

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

产品实体一对多

  a b mean
1 1 2  5.5
2 1 2  3.5
3 1 2 14.5
4 2 1  5.5
5 2 1  3.5

ProductType实体

import Foundation
import RealmSwift

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

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

产品实体一对一

import Foundation
import RealmSwift

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

查询示例

import Foundation
import RealmSwift

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

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

2 个答案:

答案 0 :(得分:3)

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

let rmProducts = realm.objects(Product.self).filter("SUBQUERY(productTypeList, $type, $type.typeName == %@).@count>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

答案 1 :(得分:2)

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

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

只有在每个要匹配的子对象上需要多个条件时,才需要在另一个答案中建议SUBQUERY。例如,如果您想查找包含指定类型的项目的Products,其网址以https://开头,您将使用SUBQUERY

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