【问题标题】:How to fetch only a subset of to-many relationships in Core Data and NSPredicate如何在 Core Data 和 NSPredicate 中仅获取一对多关系的子集
【发布时间】:2017-08-23 12:16:27
【问题描述】:

这把我逼疯了……

我有一个涉及事件的模型(每个事件与 RecordEntries 有一对多的关系),如下所示:

Event <---recordEntries--->> RecordEntry

我想要做的是获取一个事件和所有与特定年龄组、性别和省份匹配的相关记录条目(过滤掉不匹配的记录条目)。需要明确的是,我需要 Event 对象,但我不需要所有 recordEntries - 我只对 Event 中所有 recordEntries 的子集感兴趣。

所以我尝试这样做:

let request = NSFetchRequest<Event>(entityName: "Event")
request.relationshipKeyPathsForPrefetching = ["recordEntries"]

request.predicate = NSPredicate(format: "SUBQUERY(%K, $r, $r.ageGroup == %i AND $r.gender == %@ AND $r.province IN %@).@count > 0", #keyPath(Event.recordEntries), ageGroupCode, userGender, ["CA", userProvince])

...我最终得到了所有记录(而不是匹配 ageGroupCode、userGender 和 ["CA", userProvinces] 的记录。

我还尝试了以下方法:

let recordAgePredicate = NSPredicate(format: "ANY recordEntries.ageGroup == %i", ageGroupCode)
let recordGenderPredicate = NSPredicate(format: "ANY recordEntries.gender == %@", userGender)
let recordProvincePredicate = NSPredicate(format: "ANY recordEntries.province IN %@", ["CA", userProvince])

request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
  recordAgePredicate, recordGenderPredicate, recordProvincePredicate
]

...这也返回了事件的所有记录(包括那些我不想要的)。

我在这里错过了什么?!?

【问题讨论】:

  • request.predicate = NSPredicate(format: "ANY (recordEntries.ageGroup == %i AND recordEntries.gender == %@ AND recordEntries.province IN %@)" ageGroupCode, the rest) 代替?
  • 如果你的意思是这样:let recordsPredicate = NSPredicate(format: "ANY (recordEntries.ageGroup == %i AND recordEntries.gender == %@ AND recordEntries.province IN %@)", ageGroupCode, userGender, ["CA", userProvince]),这将失败(无法解析格式字符串...)。
  • 如果只使用这个谓词 let recordAgePredicate = NSPredicate(format: "recordEntries.ageGroup == %i", ageGroupCode),是不是只取ageGroup等于ageGroupCode的记录?
  • @user1000 您建议的谓词导致崩溃,“此处不允许使用多对多键”...
  • @EtienneBeaule 因为您正在获取事件,所以谓词对recordEntries 关系的内容没有影响。如果您想将 recordEntries 关系过滤到您感兴趣的较小集合,请将谓词应用于relatedEntities 集合,或者单独获取与相关事件相关的RecordEntry 对象并满足您的其他标准。

标签: swift core-data nspredicate


【解决方案1】:

这个答案的功劳归于@user1000,他为我指明了正确的方向(并提供了几个代码 sn-ps 来尝试)...

事实证明@pbasdf 是正确的 - 在对 Event 进行提取时,对其 recordEntries 关系的谓词无效。

@user1000 建议将以下方法添加到 Event 类:

func recordsFilteredFor(ageGroup: Int, province: [String], gender: String) -> Set<RecordEntry>{
    let pred = NSPredicate(format: "ageGroup == %i AND province IN %@ AND gender == %@", ageGroup, province, gender)
    let result = recordEntries?.filtered(using: pred)
    return result as! Set<RecordEntry>
}

有了这个,我可以通过查看 event.recordsFilteredFor(...) 而不是 event.recordEntries 来遍历事件并仅访问我想要的记录。

我还不清楚这会对性能产生什么样的影响。使用此解决方案,我最终仍会获取超出我需要的内容,然后过滤此内容,但我没有那么多记录要处理。

我把request.relationshipKeyPathsForPrefetching = ["recordEntries"] 留在了那里,我认为我最好急切地加载所有关系,而不是在 recordsFilteredFor 方法中再次获取它们。我仍然需要仔细检查这是否有任何好处。一些初始测试表明,我仍然会在 recordsFilteredFor 方法中触发错误(这会使急切加载变得毫无意义)。

在我找到更好的东西之前,看起来这将是我的解决方案......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多