首页 > 解决方案 > 使用嵌套子查询过滤领域

问题描述

我的应用程序的数据看起来像这样。

class ShelfCollection: Object {
  let shelves: List<Shelf>
}

class Shelf: Object {
  let items: List<Item>
}

class Item: Object {
  var name: String
  let infos: List<String>
}

我正在尝试获取架子集合中的所有架子,其中任何项目都通过名称或信息列表中的元素与查询匹配。据我了解,这个谓词应该是正确的,但它崩溃了。

let wildQuery = "*" + query + "*"
shelfResults = shelfCollection.shelves.filter(
    "SUBQUERY(items, $item, $item.name LIKE[c] %@ OR SUBQUERY($item.infos, $info, info LIKE[c] %@).@count > 0).@count > 0",
    wildQuery, wildQuery
)

它符合 NSPredicate,但是当 Realm 尝试解析它时崩溃,把我扔了

'RLMException', reason: 'Object type '(null)' not managed by the Realm'

我怀疑嵌套子查询可能是失败的原因,但我对确定的了解还不够NSPredicate。这是一个可接受的查询,我怎样才能使它..工作?

标签: iosswiftrealmnspredicate

解决方案


这是一个答案和一个解决方案,但是对象的结构方式会存在许多问题,这可能会导致其他问题。由于许多对象出现在其他对象中,因此很难创建匹配的数据集。

问题:

领域目前无法过滤原语列表

编辑: 10.7 版增加了对过滤器/查询以及原语上的聚合函数的支持,因此以下信息不再完全有效。但是,仍然需要注意。

所以这个 Item 属性不适用于过滤:

let infos: List<String>

但是,您可以创建另一个具有 String 属性的对象并对该对象进行过滤

class InfoClass: Object {
    @objc dynamic var info_name = ""
}

然后 Item 类看起来像这样

class Item: Object {
  var name: String
  let infos = List<InfoClass>()
}

然后您根据 InfoClass对象进行过滤,而不是它的字符串属性。所以你会有一些对象

let info0 = InfoClass()
info0.info_name = "Info 0 name"
    
let info1 = InfoClass()
info1.info_name = "Info 1 name"

let info2 = InfoClass()
info2.info_name = "Info 2 name"

它们存储在 Item->infos 列表中。那么问题

我正在尝试将所有架子放在架子集合中...

表示您要过滤一个集合,在本例中为 c0,其项目在其列表中包含特定信息的货架。假设我们想要获取列表中包含 info2 的那些货架

 //first get the info2 object that we want to filter for
 guard let info2 = realm.objects(InfoClass.self).filter("info_name == 'Info 2 name'").first else {
    print("info2 not found")
    return
}

print("info2 found, continuing")

//get the c0 collection that we want to get the shelves for
if let c0 = realm.objects(ShelfCollection.self).filter("collection_name == 'c0'").first {
    let shelfResults = c0.shelves.filter("ANY items.infoList == %@", info2)
    for shelf in shelfResults {
        print(shelf.shelf_name)
    }
} else {
    print("c0 not found")
}

我省略了对 name 属性的过滤,因为您已经知道如何做到这一点。

这里的问题是信息可能出现在许多项目中,而这些项目可能出现在许多货架列表中。因此,由于数据的深度,对于我的测试数据,很难让过滤器返回谨慎的数据 - 如果我有示例数据可以使用,它可能会更有意义(对我来说)。

无论哪种方式,答案都适用于这个用例,但我认为另一种结构可能更好,但我不知道完整的用例,所以很难建议。


推荐阅读