SQLite 之FTS5全文检索

第一节 ICU下载和编译


ICU 主页 : http://site.icu-project.org/
考虑使用MSVC2015编译,选择ICU4C 59.1版本
下载地址 : http://site.icu-project.org/download/59#TOC-ICU4C-Download

Window版编译:
1.    解压icu4c-59_1-src.zip
2.    进入icu4c-59_1-src\icu\source\allinone目录
3.    双击allinone.sln文件启动MSVC2015
选择批生成,并选择所有win32版本,如下图所示:

点击生成,开始编译,只要版本选择正确,编译不会出错。
4.    编译结果
进入icu4c-59_1-src\icu目录,如下图:

编译结果位于:lib目录和bin目录,include是导出的头文件。
5.    部署
可以将编译结果手工部署到开发环境中。
Mac版编译:
1.    解压icu4c-59_1-src.tgz
2.    icu4c-59_1-src\icu\source目录
3.    运行configure
4.    运行make
5.    运行make install,或者手工部署(推荐手工部署)


第二节 Tokenize自定义中文分词器


1.    原理介绍
https://www.sqlite.org/fts5.html
7.1. Custom Tokenizers

重点是实现Create(),Delete()和Tokenize()三个函数。
2.    参考示例
https://github.com/TangXiaoLv/Android-Sqlite-Fts5-Tokenizer/blob/master/sqlite3/src/main/cpp/sqlite3/extra/wcicu_tokenizer.h
https://github.com/TangXiaoLv/Android-Sqlite-Fts5-Tokenizer/blob/master/sqlite3/src/main/cpp/sqlite3/extra/wcicu_tokenizer.c
示例wcicu_tokenizer是一个基于ICU的中文分词器的完整实现,这个实现可以完全copy,在Mac和Android上直接编译,Windows用MSVC编译时只需要做部分语法修正就可以编译通过。这个分词器依赖于上一节中ICU编译生成的lib、dll和头文件。


第三节 Sqlite + FTS5 + 中文分词器的集成


Sqlite与分词器和ICU的关系可以近似的用下图表示:

集成步骤:
1.    编译ICU(见第一节)
2.    实现WCICUTokenizer自定义分析器(见第二节)
3.    将Tokenizer引入sqlite
(1)分词器实现:
参见:  wcicu_tokenizer.h和wcicu_tokenizer.c( 这个命名可以随便修改,重点是三个函数名需要注册要Sqlite中)
Create函数声明如下:

int fts5_wcicuCreate(void *pCtx, const char **azArg, int nArg, Fts5Tokenizer **ppOut);

Delete函数声明如下:

void fts5_wcicuDelete(Fts5Tokenizer *pTok);

Tokenzier函数声明如下:

int fts_wcicu_Tokenize(Fts5Tokenizer *pTokenizer,
                        void *pCtx,
                        int flags,
                        const char *pText,
                        int nText,
                        int (*xToken)(
                                      void *pCtx,
                                      int tflags,
                                      const char *pToken,
                                      int nToken,
                                      int iStart,
                                      int iEnd)
                        );

(2)将wcicu引入Sqlite
在sqlite3.c中导入分词器头文件

#include "wcicu_tokenizer.h"

在sqlite3.c中将wcicu注册为build-in的分词器,如下所示:

/*
** Register all built-in tokenizers with FTS5.
*/
static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
  struct BuiltinTokenizer {
    const char *zName;
    fts5_tokenizer x;
  } aBuiltin[] = {
    { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
    { "ascii",     {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
    { "porter",    {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
    { "wcicu",	   {fts5_wcicuCreate, fts5_wcicuDelete, fts_wcicu_Tokenize }},
  };
  
  int rc = SQLITE_OK;             /* Return code */
  int i;                          /* To iterate through builtin functions */

  for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){
    rc = pApi->xCreateTokenizer(pApi,
        aBuiltin[i].zName,
        (void*)pApi,
        &aBuiltin[i].x,
        0
    );
  }

  return rc;
}

4.    编译sqlite,生成支持自定义分词器的sqlite库

开启SQLITE_ENABLE_FTS5和SQLITE_ENABLE_ICU标志
途径一:在sqlite3.h顶部加入如下两行

#define SQLITE_ENABLE_FTS5 1
#define SQLITE_ENABLE_ICU 1

途径二:在qt工程文件中加入DEFINES

DEFINES += SQLITE_ENABLE_FTS5=1  SQLITE_ENABLE_ICU=1

 


第四节 FTS的使用和测试


基于上一节的修改,可以编译生成支持自定义分词器的SQLite Shell,方便数据测试。

1.    使用FTS5和wcicu分词器创建虚表:

2.    查看创建结果:

3.    插入数据:

4.    Select:

5.    Match:

6.    查看数据库的编码方式:

7.    设置 数据库的编码:

注意设置编码一定要在数据库创建后,所有操作之前才有效,否则设置会无效,如下所示:

8.    Highlight

代码示例:

QString cmd;
QString start = QString::fromUtf8("<label style=''color:#1abc9c;''>");
QString stop = QString::fromUtf8("</label>");
int infoColumnIndex = 4;
cmd = QString::fromUtf8("SELECT highlight(%1, %2, '%3', '%4') as %5 "
                                "FROM %1 "
                                "WHERE %1 "
                                "MATCH :%5 ").arg("city")
                                             .arg(infoColumnIndex)
                                             .arg(start)
                                             .arg(stop)
                                             .arg(QString::fromUtf8("cityname"));

 

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值