1

我有一个 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”做一个 INNER JOIN,但如果我自己重写查询,我可以简单地用一个 INNER JOIN 来完成。

在 3GS 上运行:

单个字(0.0262 秒):

CoreData: sql: SELECT DISTINCT t0.Z_ENT, t0.Z_PK, t0.ZID, t0.ZNAME FROM ZCDRECIPE t0 JOIN Z_4RECIPES t1 ON t0.Z_PK = t1.Z_5RECIPES JOIN ZCDKEYWORD t2 ON t1.Z_4KEYWORDS = t2.Z_PK WHERE NSCoreDataStringSearch( t2 .ZTERM, ?, 8, 0) 按 t0.ZNAME 排序

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

多字(0.2996 秒):

CoreData: sql: SELECT DISTINCT t0.Z_ENT, t0.Z_PK, t0.ZID, t0.ZNAME FROM ZCDRECIPE t0 JOIN Z_4RECIPES t1 ON t0.Z_PK = t1.Z_5RECIPES JOIN ZCDKEYWORD t2 ON t1.Z_4KEYWORDS = t2.Z_PK JOIN Z_4RECIPES t3 ON t0.Z_PK = t3.Z_5RECIPES JOIN ZCDKEYWORD t4 ON t3.Z_4KEYWORDS = t4.Z_PK WHERE (NSCoreDataStringSearch(t2.ZTERM, ?, 8, 0) AND NSCoreDataStringSearch(t4.ZTERM, ?, 8, 0)) 按 t0 排序。名称

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

即使它正在查看同一个表,您也可以看到,CoreData 不止一次地与 ZCDKEYWORD 进行了 INNER JOINing。

在我的谓词中,有没有办法让它只将关键字表加载到连接中?

谢谢

4

1 回答 1

2

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

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

编辑

在查找了我的旧解决方案后,我意识到您可能正在以错误的方式进行查找。这说得通。您有多个keywords查找,因此会有两个连接。

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

[NSPredicate predicateWithFormat:@"term BEGINSWITH %@", s];

得出最终结果应该只是一次内存查找:

searchResults = [searchResults filteredArrayUsingPredicate:
    [NSPredicate predicateWithFormat:@"ANY keywords IN %@", fetchedKeywords]];
于 2013-10-04T14:04:31.820 回答