阅读本教程前,建议先阅读 iOS/macOS使用教程 、 和 基础类、CRUD与Transaction 。
介绍
全文搜索 ( Full-Text Serach ),是SQLite提供的功能之一,支持更快速、更便捷地搜索数据库内的信息。更多信息可参考SQLite的官方文档。
WCDB内建FTS的支持,使用更简便,搜索更智能,分词更适合中文、日文等非空格分割的语言搜索。
基本用法
FTS的ORM与普通表的ORM很类似。
将一个已有的ObjC类进行FTS的ORM绑定的过程如下:
- 使用宏在头文件声明需要绑定到数据库表的字段。
- 使用
WCDB_SYNTHESIZE
宏在类文件定义需要绑定到数据库表的字段。 - 使用
WCDB_VIRTUAL_TABLE_MODULE
定义使用的虚拟表的模块。 - 使用
WCDB_VIRTUAL_TABLE_TOKENIZE
定义使用搜索使用的分词器。
如无特殊需求,模块和分词器可使用默认的WCTModuleNameFTS3
和WCTTokenizerNameWCDB
即可。后面会进一步讨论模块和分词器。
SQLite的FTS是使用虚拟表实现的,因此其与虚拟表有同样的限制
- 不支持创建触发器
- 不支持、也不需要创建索引
- 不支持通过
ALTER TABLE
为虚拟表添加新的字段
建表
建FTS表与建普通表也很类似。对于已经定义FTS-ORM的类WCTSampleFTSData
和已创建的数据databaseFTS
- 通过
- setTokenizer:
接口对当前数据库注册分词器,这里需与ORM定义的分词器一致。开发者也可以通过- setTokenizers:
注册多个分词器。 - 通过接口创建FTS表。
开发者只需要将数据插入到FTS表中,即可建立FTS索引。插入方式与普通表没有区别。
FTS搜索
FTS搜索与普通表的方式类似,只是在where
语句中,需要用match
来搜索。
FTS表不仅可以针对某个字段进行搜索,也可以使用内置的隐藏字段进行全表搜索。隐藏字段与表名一致,可以通过className.PropertyNamed(tableName)
获取。
FTS模块
SQLite支持FTS3
、FTS5
两种搜索模块,可通过WCDB_VIRTUAL_TABLE_MODULE(WCTSampleFTSData, WCTModuleNameFTS3)
或WCDB_VIRTUAL_TABLE_MODULE(WCTSampleFTSData, @"FTS5")
进行定义。WCDB默认使用FTS3
。
关于 FTS3
和 FTS5
的差异,可参考SQLite的官方文档 和 SQLite FTS5 Extension
FTS分词器
若只用一句话概括,FTS搜索的原理是将文字信息通过分词器切断为字词组成的数组,并以此建立搜索树。因此,分词器是搜索效率、准确度的关键。
SQLite内置了simple
、、unicode61
等多个分词器,但其适合场景有限,这里不做深入讨论,开发者可自行搜索。
这里重点讨论WCDB内置的分词器, WCTTokenizerNameApple
和 WCTTokenizerNameWCDB
。
WCTTokenizerNameApple
是WCDB内置的一个分词器,它使用 CoreFoundation
内置的 CFStringTokenizer
对语句进行分割。
CFStringTokenizer
会过滤符号,并根据语言、语义对语句进行分割。
在iOS的任一输入框的文字中长按,并在弹出菜单中点击 "选择",iOS会智能地根据当前游标选择附近的一个词组。这个就是 CFStringTokenizer
的分词效果。
以一个词组 "苹果树" 为例,CFStringTokenizer
根据语义,会将其分割为 "苹果" 和 "树" 两个词组。
因此,使用 Apple分词器 的 FTS 表内会有该两个字段。开发者只需使用 className.PropertyNamed(tableName).match("苹果")
即可搜索到对应的数据。
Apple分词器的局限性
因此,以"苹果树"的例子来说,"果树" 这一关键词因为无法首字匹配 "苹果" 和 "树",它无法被搜索到。而在中文中,这一例子里有"苹果"、"果树"、"树"、"苹果树"等多个有意义的词组。因此,虽然Apple分词器可以智能地基于语义进行分词,但其并不符合部分场景和部分语言。
同时,FTS通常用于app内搜索,其使用场景与搜索引擎不同。搜索引擎只要求将最符合条件的前几页数据搜索出来,因此搜索"果树"但结果中没有"苹果树"是符合场景的。而FTS要求的触达率要求是100%,即只要app内有这个数据,就应该被搜索出来。
WCTTokenizerNameWCDB
是WCDB内置分词器,也是我们优先推荐的分词器。
WCDB分词器会过滤所有Unicode编码中符号、空格、制表符、不可见和非法字符等。即Unicode编码字集中的 [ Cc, Cf, Z, U000A ~ U000D, U0085, M, P, S ],详情可参考
WCDB分词器会将英文按照单词进行词形还原。
以句子"WCDB is a cross-platform database framework developed by WeChat."为例,由于英文存在多种变形和时态,传统的分词器无法通过"are"搜索到"is",无法通过"develop"搜索到"developed"。而词形还原会将单词还原为一般形态,从而使得WCDB分词器有更强的英文搜索能力。
包括中文、日文在内的多种语言,都是通过语义,而不是空格或符号进行分割。WCDB分词器会将他们按照单双字符的逻辑进行分词。
同样以"苹果树"的逻辑为例,WCDB分词器会按照顺序,将其分割为:"苹果"、"苹"、"果树"、"果"、"树"。因此其可以确保各种组合都能正确匹配到。
自定义分词器
若开发者对已有的分词器不满意,也可以自定义新的分词器。
WCDB提供了文件模版用来定义分词器,开发者可参考 和 WCDB分词器 实现。