使用嵌套子查询过滤领域

Filtering Realm with nested subqueries

我的应用有这样的数据。

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 的了解还不够确定。这是一个可以接受的查询吗,我怎样才能让它.. 工作?

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

问题:

Realm 目前无法过滤基元列表

编辑: 版本 10.7 添加了对 filters/queries 的支持以及基元上的聚合函数,因此以下信息不再完全有效。不过,还是要注意一下。

因此此项 属性 将无法用于筛选:

let infos: List<String>

但是,您可以创建另一个具有字符串 属性 的对象并过滤该 对象

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

然后项目 class 看起来像这样

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 列表中。那么问题

I'm trying to get all shelves in a shelf collection...

声明您要过滤集合,在本例中为 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")
}

我省略了对名称 属性 的过滤,因为您已经知道该怎么做了。

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

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