注:示例基于iOS平台
随App里内容的增多,查找的复杂度也越来越高,用户操作就会显得很麻烦,简单举个例子,社交App的聊天记录随时间积累到一定程度的时候,想查看历史聊天记录,就得在App里慢慢翻历史消息到之前聊过的地方,查看成本非常高,这时候在App里做全文检索就显得很必要。
那全文检索的实现复杂度怎么样呢,其实只要熟悉SQLite的使用,再了解一下SQLite FTS的特性,就能很简单的添加此功能,下面就介绍一下自己的关于全文检索的理解,不足之处望指出。
FTS
首先简单介绍一下FTS,全称Full Text Search,也就是全文检索,是Sqlite自带的功能模块,基于虚表、分词器及文件实现的全文检索方案,检索结果的理想程度跟分词器有关,分词器越智能,检索结果越理想。SQLite的版本有多个,主要使用FTS3和FTS4,FTS5也发布了,但需要自己编译才能使用,详细的FTS文档参考这,下面几条主要先介绍FTS的相关概念及语法:
1.Tokenizer(分词器)
分词器是FTS的核心,没有分词器模块,FTS就没法工作,分词器主要是将输入文本进行拆分,以便SQLite进行Match,例如一段文本“全文检索”,可能被拆分为“全文、检索”,也可能本拆分为“全、文、检、索”,最终检索结果也完全取决于分词器的拆分。假设上面两种拆分分别为A和B,那全文检索的时候检索“文”和“全文”,“文”在A方案中是没法检索出文的,而B方案可以,“全文“在A、B方案中都能检索出来,这就是分词器的大概作用。
SQLite也提供了相关分词器,比如simple、icu、unicode61等,只有icu、unicode61支持中文,但unicode61按标点拆分,不可用,而icu是按字拆分的,可以用,只是检索结果会比较乱。
2.MATCH
MATCH是FTS的检索操作,MATCH会比LIKE快上很多倍,MATCH是全匹配,MATCH还可以执行MATCH * 操作,类似于LIKE 的后%操作,就是前缀匹配,下面会有使用实例,继续。
3.offsets
offset类似于SQLite里的count,是一个功能函数,获取匹配结果在文本中的位置偏移,最终会获取到匹配文本在数据表中的第几行、第几列、已经匹配文本的Range,详细参考官方文档。
4.snippet
snippet也类似于offsets,都是用于获取匹配文本的位置,方便查询结果的高亮处理,语法如下:snippet(table name, [, ], …, 1, 10) as text;参数分别是table name、关键字左括弧、关键字右括弧、省略符,生效列,关键字前后字符限制,例如在文本“xxxxxxxxxxxxxx位置xxxxxxxxxxxx”中Match“位置”,得到的结果为:“…xxxxxxxxxx[位置]xxxxxxxxxx…”。简单说就是将匹配到的文本括起来,这里用的[]括号,匹配位置距文本首尾过长都会以指定的…省略。
FMDB(FTS)
iOS平台的FMDB在最新版本中拓展了FTS3的支持,其拓展简单理解就是自定义分词器的接入,FMDB基于CFStringTransform实现了以词为单位做拆分的分词器,基本能满足检索需要。下面是FMDB加载自定义分词器的示例代码:
|
|
不使用FMDB的话也可以按官方文档实现分词器模块,并以SQL语句直接注册自定义分词器,参考如下FMDB代码:
全文检索
首先创建FTS虚拟表,指定分词器为(fmdb simple),分词器的注册如上文介绍,创建语法如下:
更新数据到FTS表:
群文检索语法:
高亮显示:有上面offsets和snippet两种方式获取关键字range(一般使用snippet),文本高亮的显示就很简单了。