在文本中搜索匹配的单词时,可以优化Core Data查询吗?(此问题还与iPhone上的自定义SQL与核心数据的智慧有关。)
我正在开发一个新的(iPhone)应用程序,该应用程序是用于科学数据库的手持式参考工具。主界面是一个标准的可搜索表格视图,我希望在用户键入新单词时按需键入响应。单词匹配必须是文本中单词的前缀。文本由十万个单词组成。
在我的原型中,我直接编码了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非常重要,可以让我快速显示结果。如果达到限制,我会通知用户太多显示。这很糊涂。
在过去的几天中,我一直在思考迁移到Core Data的优势,但是我担心模式,索引和对重要查询的查询缺乏控制。
从理论上讲,NSPredicatetextField MATCHES '.*\bfoo.*'会起作用,但是我敢肯定它会很慢。这种文本搜索似乎很常见,我不知道常见的攻击是什么?您是否会像我上面那样创建一个单词实体,并使用“单词BEGINSWITH’foo’”的谓词?那会和我的原型一样快吗?核心数据会自动创建正确的索引吗?我找不到建议持久存储有关索引的任何明确方法。
textField MATCHES '.*\bfoo.*'
我在iPhone应用程序中看到了Core Data的一些不错的优点。故障和其他内存考虑因素允许对表视图查询进行有效的数据库检索,而无需设置任意限制。对象图管理使我无需编写大量SQL即可轻松遍历实体。将来迁移功能会很不错。另一方面,在有限的资源环境(iPhone)中,我担心自动生成的数据库会充斥着元数据,不必要的逆关系,效率低下的属性数据类型等。
我应该潜入还是谨慎行事?
我提出了一种解决方法。我认为这与这篇文章相似。我将合并源代码添加到我的Core Data项目中,然后创建了不是托管对象子类的全文本搜索类。在FTS类中,我使用I #import "sqlite3.h"(源文件)而不是sqlite框架。FTS类将保存到与Core Data持久性存储不同的.sqlite文件。
#import "sqlite3.h"
导入数据时,核心数据对象将相关FTS对象的rowid存储为整数属性。我有一个静态数据集,所以我不必担心引用完整性,但是维护完整性的代码应该很简单。
要执行FTS,我MATCH查询FTS类,返回一组rowid。在我的托管对象类中,我使用来查询相应的对象[NSPredicate predicateWithFormat:@"rowid IN %@", rowids]。我避免以这种方式遍历任何多对多关系。
MATCH
[NSPredicate predicateWithFormat:@"rowid IN %@", rowids]
性能显着提高。我的数据集是142287行,包括194MB(核心数据)和92MB(已删除停用词的FTS)。根据搜索字词的频率,对于不频繁的字词(<100个匹配),我的搜索时间从几秒变到了0.1秒;对于频繁的字词(> 2000个匹配数),我的搜索时间变成了0.2秒。
我敢肯定我的方法有很多问题(代码膨胀,可能的名称空间冲突,某些核心数据功能的丢失),但是它似乎可以正常工作。