是否有一个 NSPredicate 来过滤具有一对多关系的模型(过滤多个)?

Posted

技术标签:

【中文标题】是否有一个 NSPredicate 来过滤具有一对多关系的模型(过滤多个)?【英文标题】:Is there a NSPredicate to filter models with one-to-many relationship (filter the many)? 【发布时间】:2019-03-25 21:21:12 【问题描述】:

我有两个模型:专辑和歌曲,专辑包含 N 首歌曲,但歌曲仅包含 1 张专辑。我正在尝试制作一个特定的过滤器,但我找不到一个可以给我预期结果的 NSPredicate。

我在 CoreData 上创建了两个模型:

所以我创建了一些对象:

let song1 = Song(context: context)
song1.name = "I Love You"
song1.composer = "Ana"

let song2 = Song(context: context)
song2.name = "Hello And Goodbye"
song2.composer = "Ben"

let song3 = Song(context: context)
song3.name = "I Miss You"
song3.composer = "Marie"

let song4 = Song(context: context)
song4.name = "Lonely"
song4.composer = "Ana"

let album = Album(context: context)
album.name = "Love Songs 1"
let set = NSSet(array: [song1, song2, song3])
album.addToSong(set)

let album2 = Album(context: context)
album2.name = "Love Songs 2"
let set2 = NSSet(array: [song4])
album2.addToSong(set2)

所以,我想做这个过滤器:

获取 Ana 是作曲家且歌曲名称包含“n”的专辑

我正在使用此谓词获取专辑模型:

let composerPredicate = NSPredicate(format: "ANY song.composer = %@", "Ana")
let songPredicate = NSPredicate(format: "ANY song.name contains %@", "n")

let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [composerPredicate, songPredicate])

但在获取的结果中,我得到了两张专辑,但我只想返回“Love Songs 2”。

你知道我该怎么做吗?

EDIT1:我想找到一个不使用任何映射、过滤器或循环(如果可能的话)的解决方案,因为它直接影响性能,因为我处理了很多数据。

【问题讨论】:

Song2 的标题中有一个n,因此应该返回两张专辑,因为您使用了ANY 我无法删除 ANY,因为它因以下错误而崩溃:“由于未捕获的异常 'NSInvalidArgumentException' 导致应用程序终止,原因:'此处不允许多对多键'” 【参考方案1】:

您需要使用 SUBQUERY,因为只有当专辑的歌曲同时符合这两个条件时,您才想包含专辑。 (您的复合谓词将包括一张专辑,其中有一首歌曲符合第一个条件,另一首歌曲符合第二个条件)。

let predicate = NSPredicate(format: "SUBQUERY(song, $S, $S.composer == %@ AND $S.name contains %@).@count > 0", “Ana”, "n")

【讨论】:

这非常适合我的问题!非常感谢!我以前从未使用过子查询,所以我不知道这可能是一个解决方案。 你知道如何按歌曲名称对专辑进行排序吗?也使用谓词或 sortDescriptors。 您不能按歌曲名称对专辑进行排序,因为每个专辑都有很多歌曲。您只能按属性或一对一关系排序。

以上是关于是否有一个 NSPredicate 来过滤具有一对多关系的模型(过滤多个)?的主要内容,如果未能解决你的问题,请参考以下文章

在一对多关系中使用 NSPredicate 进行过滤

CoreData:使用 NSPredicate 过滤一对多对多关系(此处不允许错误对多键)

Core Data NSPredicate 按数组中的项目过滤项目集

NSPredicate 返回重复值

如何根据多对关系集是不是包含特定值使用 NSPredicate 进行过滤

如何设置 NSPredicate 来检查关系的属性?