如何优化全文搜索的 Core Data 查询

2023-12-31

在文本中搜索匹配单词时可以优化核心数据查询吗? (这个问题也涉及到 iPhone 上自定义 SQL 与 Core Data 的区别。)

我正在开发一款新的(iPhone)应用程序,它是科学数据库的手持参考工具。主界面是一个标准的可搜索表格视图,我希望在用户输入新单词时得到即时响应。单词匹配必须是文本中单词的前缀。文本由 100,000 个单词组成。

在我的原型中,我直接编写了 SQL 代码。我创建了一个单独的“单词”表,其中包含主实体文本字段中的每个单词。我对单词进行了索引并按照以下方式进行了搜索

SELECT id, * FROM textTable 
  JOIN (SELECT DISTINCT textTableId FROM words 
         WHERE word BETWEEN 'foo' AND 'fooz' ) 
    ON id=textTableId
 LIMIT 50

这运行得非常快。使用 IN 可能也同样有效,即

SELECT * FROM textTable
 WHERE id IN (SELECT textTableId FROM words 
               WHERE word BETWEEN 'foo' AND 'fooz' ) 
 LIMIT 50

LIMIT 至关重要,它可以让我快速显示结果。我通知用户,如果达到限制,则显示太多。这很糟糕。

在过去的几天里,我一直在思考迁移到核心数据的优势,但我担心对重要查询的架构、索引和查询缺乏控制。

理论上的 NSPredicatetextField MATCHES '.*\bfoo.*'会起作用,但我确信它会很慢。这种文本搜索似乎很常见,我想知道通常的攻击是什么?您会像我上面那样创建一个单词实体并使用“word BEGINSWITH 'foo'”谓词吗?它的工作速度会像我的原型一样快吗? Core Data 会自动创建正确的索引吗?我找不到任何明确的方法来向持久存储提供关于索引的建议。

我在我的 iPhone 应用程序中看到了 Core Data 的一些很好的优势。故障和其他内存考虑因素允许对表视图查询进行高效的数据库检索,而无需设置任意限制。对象图管理使我能够轻松遍历实体,而无需编写大量 SQL。将来迁移功能会很好。另一方面,在有限的资源环境(iPhone)中,我担心自动生成的数据库会因元数据、不必要的反向关系、低效的属性数据类型等而变得臃肿。

我应该潜入还是谨慎行事?


我做了一个解决方案。我认为它类似于这个帖子 https://stackoverflow.com/questions/1878962/full-text-searching-in-apples-core-data-framework/2076064#2076064。我将合并源代码添加到我的 Core Data 项目中,然后创建一个不是托管对象子类的全文搜索类。在 FTS I 类中#import "sqlite3.h"(源文件)而不是 sqlite 框架。 FTS 类保存到与 Core Data 持久存储不同的 .sqlite 文件。

当我导入数据时,Core Data 对象将相关 FTS 对象的 rowid 存储为整数属性。我有一个静态数据集,因此我不担心引用完整性,但维护完整性的代码应该很简单。

为了执行 FTS,我MATCH查询 FTS 类,返回一组 rowid。在我的托管对象类中,我使用以下命令查询相应的对象[NSPredicate predicateWithFormat:@"rowid IN %@", rowids]。我避免以这种方式遍历任何多对多关系。

性能的提升是巨大的。我的数据集有 142287 行,包括 194MB(核心数据)和 92MB(删除停用词的 FTS)。根据搜索词频率的不同,我的搜索时间从几秒变为不常见词(2000 次点击)的搜索时间为 0.2 秒。

我确信我的方法存在无数问题(代码膨胀、可能的命名空间冲突、丢失一些核心数据功能),但它似乎有效。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何优化全文搜索的 Core Data 查询 的相关文章

随机推荐