Ios 核心数据任意多个内部连接

Ios 核心数据任意多个内部连接,ios,core-data,nspredicate,Ios,Core Data,Nspredicate,我有一个CoreData模型,它有一个可搜索的“配方”对象的大列表。为了提高搜索效率,我有一个名为“关键字”的引用模型,它只是有一个“术语”属性(索引)。该术语是一个单词,根据“配方”名称进行处理和规范化 因此,例如,如果一个配方被称为Crème Brèlée,它将有两个关键字“creme”和“brulee”,那么我也会规范用户的搜索,以便他们可以使用重音词来查找非重音词,反之亦然 当用户搜索时,我获取字符串,进行规范化,然后按空格分割。搜索配方结果的关键字必须以所有拆分搜索组件开头 我创建了一

我有一个CoreData模型,它有一个可搜索的“配方”对象的大列表。为了提高搜索效率,我有一个名为“关键字”的引用模型,它只是有一个“术语”属性(索引)。该术语是一个单词,根据“配方”名称进行处理和规范化

因此,例如,如果一个配方被称为Crème Brèlée,它将有两个关键字“creme”和“brulee”,那么我也会规范用户的搜索,以便他们可以使用重音词来查找非重音词,反之亦然

当用户搜索时,我获取字符串,进行规范化,然后按空格分割。搜索配方结果的关键字必须以所有拆分搜索组件开头

我创建了一个动态谓词,它根据用户正在搜索的单词数量增长

如果您正在搜索“crem”,则谓词将类似于:

[NSPredicate predicateWithFormat:@"ANY keywords.term BEGINSWITH %@", @"crem"]
如果您搜索“crem bru”:

[NSPredicate predicateWithFormat:@"ANY keywords.term BEGINSWITH %@ AND ANY keywords.term BEGINSWITH %@", @"crem", @"bru"]
现在,我面临的问题。

用一个词,这是燃烧得很快。我能够在3GS上运行它,没有明显的延迟和实时搜索建议。当您在搜索中添加后续单词时,问题就出现了。我已经查看了SQL输出,我认为问题在于CoreData正在按照“ANY keywords.term BEGINSWITH”进行内部连接,但是如果我自己重写查询,我可以简单地使用单个内部连接来完成

在3GS上运行:

单个字(0.0262秒):

CoreData:sql:选择DISTINCT t0.Z_ENT、t0.Z_PK、t0.ZID、t0.ZNAME 从ZCDRECIPE t0加入t0上的Z_4配方t1.Z_PK=t1.Z_5配方加入 ZCDKEYWORDt1.Z_4KEYWORDS=t2.Z_PK上的t2,其中 NSCoreDataStringSearch(t2.ZTERM,?,8,0)按t0.ZNAME排序

CoreData:注释:sql连接获取时间:0.0262s

多字(0.2996秒):

CoreData:sql:选择DISTINCT t0.Z_ENT、t0.Z_PK、t0.ZID、t0.ZNAME 从ZCDRECIPE t0加入t0上的Z_4配方t1.Z_PK=t1.Z_5配方加入 ZCDKEYWORDt1上的t2.Z_4KEYWORDS=t2.Z_PK加入t3上的Z_4RECIPES t0.Z_PK=t3.Z_5食谱加入ZCDKEYWORDt3.Z_4KEYWORDS=t4.Z_PK上的t4 其中(NSCoreDataStringSearch(t2.ZTERM,?,8,0)和 NSCoreDataStringSearch(t4.ZTERM,?,8,0))按t0.ZNAME订购

CoreData:注释:sql连接获取时间:0.2996s

您可以看到,尽管CoreData查看的是同一个表,但它与ZCDKEYWORD的内部连接不止一次

在我的谓词中,有没有一种方法可以使它只将关键字表加载一次到联接中


谢谢

尝试使用复合谓词语法。在类似的情况下,我使用此设置获得了非常好的结果

for (NSString *s in words) {
   finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:
     @[finalPredicate, [NSPredicate predicateWithFormat:
         @"ANY keywords.term BEGINSWITH %@", s]]];
}

编辑

在查找了我的旧解决方案后,我意识到您可能正在以错误的方式进行查找。这是有道理的。您有多个
关键字
查找,因此将有两个联接

从关系中的其他实体派生所需的数据可能更好。谓词应直接引用关键字实体:

[NSPredicate predicateWithFormat:@"term BEGINSWITH %@", s];
导出最终结果应该只是一个内存查找:

searchResults = [searchResults filteredArrayUsingPredicate:
    [NSPredicate predicateWithFormat:@"ANY keywords IN %@", fetchedKeywords]];

你是如何构造谓词的?使用字符串?使用字符串,它们相当于我文章中的代码,但是通过for循环生成,因此用户键入的每个单词都有自己的匹配。这仍然在SQL查询中进行两次连接CoreData在引擎盖下进行。考虑到这一点,也许你必须反过来进行查找。请参阅我的编辑。第二个代码段中的第一个“searchResults”数组来自何处?如果都在内存中,我有数千行,所以我不知道这会有多好。此外,如果它需要为过滤器的每次迭代引用多对多表,这可能比我当前的实现慢:(核心数据提供了“出错”机制),这样即使是一个大的对象数组也不会对内存造成太大的压力。第一个
搜索结果将是键入一个字母后的第一个结果,还有什么?在内存中过滤数组不应该是一个性能问题。--顺便说一句,WWDC 2011视频中描述了同样的模式。