具有多对多谓词的核心数据

Posted

技术标签:

【中文标题】具有多对多谓词的核心数据【英文标题】:Core Data with multiple to Many Predicates 【发布时间】:2011-02-25 17:07:12 【问题描述】:

对于这样的关系:

标签组>标签>对象

一个Object有标签,标签可以通过tagGroups进行分组。

我有一个对象,我想知道它的标签所属的所有 TagGroups。

为了构造他的谓词,我首先尝试了以下格式字符串:

(SELF 是一个 TagGroup)

NSPredicate* p = [NSPredicate predicateWithFormat:@"%@ IN SELF.tags.objects" , object];

这失败了,因为集合没有通过 Key-ValueCoding 遍历。

经过一些研究,我发现了几个解释 SUBQUERY 的问题

Core Data, try to use NSPredicate to filter a toMany relationship set but get the "to-many key not allowed here" error

Core data to-many NSPredicate with AND

这些似乎是解决方案的一部分,但与这些问题不同,我不是在测试像“tag.name”这样的值,而是在集合中的成员身份。

考虑到这一点,我尝试了这个:

NSPredicate* p = [NSPredicate predicateWithFormat:@"%@ IN SUBQUERY(SELF.tags, $eachTag,$eachTag.object)" , object];

无法解析(我也尝试了其他一些变体,但均未成功)

关于如何正确构造此格式字符串的任何想法?

更新:

也从另一个方向尝试过:

NSPredicate* p = [NSPredicate predicateWithFormat:@"ALL SUBQUERY(%@.tags,$eachTag,$eachTag.tagGroup)" , anObject];

【问题讨论】:

如果 CoreData 可以将 SUBQUERY 表达式转换为 SQL 语句,我会感到非常惊讶。不过,我可能是错的。 直到我开始挖掘有关使用 NSFR 获取多对多关系的信息时,我才意识到这一点。 【参考方案1】:

如果您“有一个对象”,即您有一个特定的 managedObject,其实体为 Object,那么您不需要谓词。你只需要走关系关键路径。

这是一个使用字典实现的示例,它与托管对象的工作方式相同。

NSDictionary *tagGroup1=[NSDictionary dictionaryWithObjectsAndKeys:@"tagGroupOne",@"name",@"tagGroup1",@"theValue",nil];
NSDictionary *tagGroup2=[NSDictionary dictionaryWithObjectsAndKeys:@"tagGroupTwo",@"name",@"tagGroup2",@"theValue",nil];
NSDictionary *tag1=[NSDictionary dictionaryWithObject:tagGroup1 forKey:@"tagGroup"];
NSDictionary *tag2=[NSDictionary dictionaryWithObject:tagGroup2 forKey:@"tagGroup"];

NSSet *tags=[NSSet setWithObjects:tag1,tag2,nil];

NSDictionary *objD=[NSDictionary dictionaryWithObjectsAndKeys:tags,@"tags",nil];
NSLog(@"tagGroup names=%@",[objD valueForKeyPath:@"tags.tagGroup.name"]);
NSLog(@"tagGroup objects=%@",[objD valueForKeyPath:@"tags.tagGroup"]);

...输出:

tagGroup names=(
    tagGroupTwo,
    tagGroupOne
)

tagGroup objects=(
        
        name = tagGroupTwo;
        theValue = tagGroup2;
    ,
        
        name = tagGroupOne;
        theValue = tagGroup1;
    
)

所以,实际上你只需要这样一行:

NSSet *tagGroups=[anInstanceOfObject valueForKeyPath:@"tags.tagGroup"];

这就是键值编码的威力。

如果您尝试获取与具有特定属性值的TagGroup 有关系的Objects,则只需要一个子查询。

【讨论】:

谢谢,问题是我正在尝试构建一个 NSFetchRequest 以供 NSFetchedResultsController 使用。我打算这样做,所以我不必将所有中间对象都放入内存中,这样我就可以依靠 NSFRC 来处理批处理结果。最后,我最终得到了像您这样的解决方案,但这并不理想。应该有一种方法可以正确构造 SUBQUERY 以获得结果

以上是关于具有多对多谓词的核心数据的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate 在核心数据中的多对多关系

预加载具有多对多关系的核心数据的最佳实践

来自核心数据多对多关系的随机实体

Core Data 多对多谓词(再次)

具有多对多关系的核心数据 NSPredicate

核心数据。加入 2 个具有多对多关系的表?