久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

SQLite FTS5 Extension (Full

 卡瑞吉 2021-05-08

1. FTS5概述

2.編譯和使用FTS5

2.1.構(gòu)建FTS5作為SQLite的一部分

2.2.構(gòu)建可裝載的擴(kuò)展

3.全文查詢語(yǔ)法

3.1.FTS5字符串

3.2.FTS5短語(yǔ)

3.3.FTS5前綴查詢

3.4.FTS5 NEAR查詢

3.5.FTS5柱過濾器

3.6.FTS5布爾運(yùn)算符

4. FTS5表創(chuàng)建和初始化

4.1.UNINDEXED列選項(xiàng)

4.2.前綴索引

4.3.斷詞

4.3.1.Unicode61 Tokenizer

4.3.2.Ascii Tokenizer

4.3.3. Porter Tokenizer

4.4.外部?jī)?nèi)容和無內(nèi)容表格

4.4.1.無內(nèi)容表格

4.4.2.外部?jī)?nèi)容表

4.5.Columnsize選項(xiàng)

4.6.詳細(xì)選項(xiàng)

5.輔助功能

5.1.內(nèi)置輔助功能

5.1.1.bm25()函數(shù)

5.1.2.highlight()函數(shù)

5.1.3.snippet()函數(shù)

5.2.通過輔助功能結(jié)果排序

6.特殊的INSERT命令

6.1.'automerge'配置選項(xiàng)

6.2.'危機(jī)綜合'配置選項(xiàng)

6.3.'刪除'命令

6.4.'全部刪除'命令

6.5.'完整性檢查'命令

6.6.'合并'命令

6.7.'優(yōu)化'命令

6.8.'pgsz'配置選項(xiàng)

6.9.'等級(jí)'配置選項(xiàng)

6.10.'重建'命令

6.11.'usermerge'配置選項(xiàng)

7.擴(kuò)展FTS5

7.1.自定義標(biāo)志符

7.1.1.同義詞支持

7.2.自定義輔助功能

7.2.1.自定義輔助函數(shù)API參考

8. fts5vocab虛擬表模塊

附錄A:與FTS3/4的比較

應(yīng)用程序移植指南

對(duì)CREATE VIRTUAL TABLE語(yǔ)句的更改

對(duì)SELECT語(yǔ)句的更改

輔助功能更改

其他事宜

技術(shù)差異總結(jié)

FTS5是一個(gè)SQLite虛擬表模塊,為數(shù)據(jù)庫(kù)應(yīng)用程序提供全文搜索功能,。在最基本的形式中,,全文搜索引擎允許用戶高效地搜索包含一個(gè)或多個(gè)搜索詞實(shí)例的子集的大量文檔,。Google向全球網(wǎng)絡(luò)用戶提供的搜索功能是全文搜索引擎,因?yàn)樗试S用戶搜索網(wǎng)絡(luò)上包含例如術(shù)語(yǔ)“fts5”的所有文檔,。

為了使用FTS5,,用戶使用一列或多列創(chuàng)建一個(gè)FTS5虛擬表。例如:

CREATE VIRTUAL TABLE email USING fts5(sender, title, body);

將類型,,約束或PRIMARY KEY聲明添加到用于創(chuàng)建FTS5表的CREATE VIRTUAL TABLE語(yǔ)句中是錯(cuò)誤的,。創(chuàng)建完成后,可以使用INSERT,,UPDATE或DELETE語(yǔ)句像任何其他表一樣填充FTS5表,。像其他沒有PRIMARY KEY聲明的表一樣,F(xiàn)TS5表有一個(gè)名為rowid的隱式INTEGER PRIMARY KEY字段,。

在上面的例子中沒有顯示的是,,作為CREATE VIRTUAL TABLE語(yǔ)句的一部分,還可以向FTS5提供各種選項(xiàng),,以配置新表的各個(gè)方面,。這些可用于修改FTS5表格從文檔和查詢中提取術(shù)語(yǔ)的方式,在磁盤上創(chuàng)建額外索引以加速前綴查詢,,或者創(chuàng)建一個(gè)FTS5表格作為其他地方存儲(chǔ)的內(nèi)容的索引,。

填充后,有三種方法可以對(duì)FTS5表的內(nèi)容執(zhí)行全文查詢:

  • 在SELECT語(yǔ)句的WHERE子句中使用MATCH運(yùn)算符,,或
  • 在SELECT語(yǔ)句的WHERE子句中使用equals(“=”)運(yùn)算符,,或
  • 使用表值函數(shù)語(yǔ)法。

如果使用MATCH或=運(yùn)算符,,則MATCH運(yùn)算符左邊的表達(dá)式通常是FTS5表的名稱(指定列過濾器時(shí)是例外),。右側(cè)的表達(dá)式必須是指定要搜索的術(shù)語(yǔ)的文本值。對(duì)于表值函數(shù)語(yǔ)法,,要搜索的術(shù)語(yǔ)被指定為第一個(gè)表格參數(shù),。例如:

-- Query for all rows that contain at least once instance of the term
-- "fts5" (in any column). The following three queries are equivalent.
SELECT * FROM email WHERE email MATCH 'fts5';
SELECT * FROM email WHERE email = 'fts5';
SELECT * FROM email('fts5');

默認(rèn)情況下,F(xiàn)TS5全文搜索是與個(gè)案無關(guān)的,。與其他任何不包含ORDER BY子句的SQL查詢一樣,,上面的示例以任意順序返回結(jié)果。要按照相關(guān)性對(duì)結(jié)果進(jìn)行排序(最相關(guān)性最低),,可以將ORDER BY添加到全文查詢中,,如下所示:

-- Query for all rows that contain at least once instance of the term
-- "fts5" (in any column). Return results in order from best to worst
-- match.  
SELECT * FROM email WHERE email MATCH 'fts5' ORDER BY rank;

除了匹配行的列值和rowid之外,應(yīng)用程序還可以使用FTS5輔助函數(shù)檢索有關(guān)匹配行的額外信息,。例如,,可以使用輔助函數(shù)為匹配行檢索列值的副本,其中匹配項(xiàng)的所有實(shí)例都由html <b> </ b>標(biāo)記包圍,。除了將FTS5表的名稱指定為第一個(gè)參數(shù)外,,輔助函數(shù)的調(diào)用方式與SQLite標(biāo)量函數(shù)相同,。例如:

-- Query for rows that match "fts5". Return a copy of the "body" column
-- of each row with the matches surrounded by <b></b> tags.
SELECT highlight(email, 2, '<b>', '</b>') FROM email('fts5');

下面提供了有關(guān)可用輔助功能的說明以及有關(guān)特殊“等級(jí)”列配置的更多詳細(xì)信息。自定義輔助函數(shù)也可以在C中實(shí)現(xiàn)并在FTS5中注冊(cè),,就像自定義SQL函數(shù)可能在SQLite內(nèi)核中注冊(cè)一樣,。

除了搜索包含術(shù)語(yǔ)的所有行外,F(xiàn)TS5還允許用戶搜索包含以下內(nèi)容的行:

  • 任何以指定前綴開頭的術(shù)語(yǔ),,
  • “短語(yǔ)” - 必須在文檔中用于匹配查詢的術(shù)語(yǔ)或前綴術(shù)語(yǔ)序列,,
  • 出現(xiàn)在彼此指定的鄰近范圍內(nèi)的術(shù)語(yǔ),前綴術(shù)語(yǔ)或短語(yǔ)集合(這些被稱為“近似查詢”),,或者
  • 任何上述的布爾組合,。

通過提供更復(fù)雜的FTS5查詢字符串作為MATCH運(yùn)算符右側(cè)的文本(或=運(yùn)算符,或者作為表值函數(shù)語(yǔ)法的第一個(gè)參數(shù)),,可以請(qǐng)求這種高級(jí)搜索,。完整的查詢語(yǔ)法在這里描述。

2.1.構(gòu)建FTS5作為SQLite的一部分

版本3.9.0(2015-10-14)開始,,F(xiàn)TS5作為SQLite合并的一部分包含在內(nèi),。它默認(rèn)是禁用的。如果使用兩個(gè)autoconf編譯系統(tǒng),,則在運(yùn)行configure腳本時(shí)通過指定“--enable-fts5”選項(xiàng)來啟用它。

或者,,如果使用其他構(gòu)建系統(tǒng)編譯sqlite3.c,,則需要安排定義SQLITE_ENABLE_FTS5預(yù)處理器符號(hào)。

2.2.構(gòu)建可裝載的擴(kuò)展

或者,,F(xiàn)TS5可以構(gòu)建為可加載的擴(kuò)展,。

規(guī)范的FTS5源代碼由SQLite源代碼樹的“ext / fts5”目錄中的一系列* .c和其他文件組成。構(gòu)建過程將其減少為只有兩個(gè)文件 - “fts5.c”和“fts5.h” - 可用于構(gòu)建SQLite可加載擴(kuò)展,。

  1. 從Fossil中獲取最新的SQLite代碼,。
  1. 按照如何編譯SQLite中的描述創(chuàng)建一個(gè)Makefile。
  1. 構(gòu)建“fts5.c”目標(biāo),。這也創(chuàng)建fts5.h.
$ wget -c http://www./src/tarball/SQLite-trunk.tgz?uuid=trunk -O SQLite-trunk.tgz
.... output ...
$ tar -xzf SQLite-trunk.tgz
$ cd SQLite-trunk
$ ./configure && make fts5.c
... lots of output ...
$ ls fts5.[ch]
fts5.c        fts5.h

然后,,可以將“fts5.c”中的代碼編譯為可加載的擴(kuò)展或靜態(tài)鏈接到應(yīng)用程序中,如編譯可加載擴(kuò)展中所述,。定義了兩個(gè)入口點(diǎn),,它們都做同樣的事情:

  • sqlite3_fts_init
  • sqlite3_fts5_init

另一個(gè)文件“fts5.h”不需要編譯FTS5擴(kuò)展。它由實(shí)現(xiàn)定制FTS5標(biāo)記器或輔助功能的應(yīng)用程序使用,。

以下塊包含BNF格式的FTS查詢語(yǔ)法摘要,。詳細(xì)的解釋如下。

<phrase>    := string [*]
<phrase>    := <phrase> + <phrase>
<neargroup> := NEAR ( <phrase> <phrase> ... [, N] )
<query>     := [ [-] <colspec> :] <phrase>
<query>     := [ [-] <colspec> :] <neargroup>
<query>     := [ [-] <colspec> :] ( <query> )
<query>     := <query> AND <query>
<query>     := <query> OR <query>
<query>     := <query> NOT <query>
<colspec>   := colname
<colspec>   := { colname1 colname2 ... }

3.1.FTS5字符串

在FTS表達(dá)式中,,可以用以下兩種方式之一來指定字符串

  • 通過用雙引號(hào)(")括起來,。在一個(gè)字符串中,,任何嵌入的雙引號(hào)字符都可以通過添加第二個(gè)雙引號(hào)字符來轉(zhuǎn)義SQL風(fēng)格。
  • 作為不是“AND”,,“OR”或“NOT”(區(qū)分大小寫)的FTS5裸字,。FTS5裸字是一個(gè)或多個(gè)連續(xù)字符的字符串,它們都是:
-  Non-ASCII range characters (i.e. unicode codepoints greater than 127), or 
-  One of the 52 upper and lower case ASCII characters, or 
-  One of the 10 decimal digit ASCII characters, or 
-  The underscore character (unicode codepoint 96). 
-  The substitute character (unicode codepoint 26). 

包含任何其他字符的字符串必須被引用,。裸字中當(dāng)前不允許使用的字符不是引號(hào)字符,,并且目前不在FTS5查詢表達(dá)式中使用任何特殊用途,可能在將來的某個(gè)時(shí)間點(diǎn)被允許使用裸詞或用于實(shí)現(xiàn)新的查詢功能,。這意味著當(dāng)前語(yǔ)法錯(cuò)誤的查詢,,因?yàn)樗鼈冊(cè)谝米址獍@樣一個(gè)字符,可能會(huì)被某些未來版本的FTS5解釋為不同,。

3.2.FTS5短語(yǔ)

FTS查詢由短語(yǔ)組成,。短語(yǔ)是一個(gè)或多個(gè)令牌的有序列表。通過將字符串傳遞給FTS表標(biāo)記器將字符串轉(zhuǎn)換為短語(yǔ),。使用“+”運(yùn)算符可以將兩個(gè)短語(yǔ)連接成一個(gè)大短語(yǔ),。例如,假設(shè)正在使用的標(biāo)記器模塊將輸入“one.two.three”標(biāo)記為三個(gè)單獨(dú)的標(biāo)記,,則以下三個(gè)查詢?nèi)恐付ㄏ嗤亩陶Z(yǔ):

... MATCH '"one two three"'
... MATCH 'one + two + three'
... MATCH '"one two" + three'
... MATCH 'one.two.three'

如果文檔包含至少一個(gè)與構(gòu)成短語(yǔ)的標(biāo)記序列相匹配的標(biāo)記子序列,,則該短語(yǔ)與文檔匹配。

3.3. FTS5 Prefix Queries

如果一個(gè)“*”字符跟在FTS表達(dá)式中的字符串之后,,那么從字符串中提取的最后一個(gè)標(biāo)記將被標(biāo)記為前綴標(biāo)記,。正如您所預(yù)料的那樣,前綴標(biāo)記可匹配任何前綴為其的文檔標(biāo)記,。例如,,以下塊中的前兩個(gè)查詢將匹配任何包含緊跟著標(biāo)記“two”的標(biāo)記“one”和任何以“thr”開頭的標(biāo)記的文檔。

... MATCH '"one two thr" * '
... MATCH 'one + two + thr*'
... MATCH '"one two thr*"'      -- May not work as expected!

上述塊中的最終查詢可能無法按預(yù)期工作,。由于“*”字符位于雙引號(hào)內(nèi),,因此它將被傳遞給標(biāo)記器,這可能會(huì)丟棄它(或者可能取決于所使用的特定標(biāo)記器,,將其包括為最終標(biāo)記的一部分)而不是識(shí)別它作為一個(gè)特殊的FTS角色,。

3.4.FTS5 NEAR查詢

兩個(gè)或更多的短語(yǔ)可以被分組到一個(gè)NEAR組中。NEAR組由標(biāo)記“NEAR”(區(qū)分大小寫),,后跟一個(gè)開括號(hào)字符,,后跟兩個(gè)或多個(gè)空白分隔的短語(yǔ)指定,后面緊跟一個(gè)逗號(hào)和數(shù)字參數(shù)N,,后跟一個(gè)右括號(hào),。例如:

... MATCH 'NEAR("one two" "three four", 10)'
... MATCH 'NEAR("one two" thr* + four)'

如果未提供N參數(shù),則默認(rèn)為10.如果文檔至少包含一個(gè)標(biāo)記叢,則NEAR組將匹配文檔:

  1. 包含每個(gè)短語(yǔ)的至少一個(gè)實(shí)例,,并且

2. 對(duì)于其中第一短語(yǔ)的端部和在叢最后一個(gè)短語(yǔ)的開始之間的令牌的數(shù)量小于或等于?,。

例如:

CREATE VIRTUAL TABLE f USING fts5(x);
INSERT INTO f(rowid, x) VALUES(1, 'A B C D x x x E F x');

... MATCH 'NEAR(e d, 4)';                      -- Matches!
... MATCH 'NEAR(e d, 3)';                      -- Matches!
... MATCH 'NEAR(e d, 2)';                      -- Does not match!

... MATCH 'NEAR("c d" "e f", 3)';              -- Matches!
... MATCH 'NEAR("c"   "e f", 3)';              -- Does not match!

... MATCH 'NEAR(a d e, 6)';                    -- Matches!
... MATCH 'NEAR(a d e, 5)';                    -- Does not match!

... MATCH 'NEAR("a b c d" "b c" "e f", 4)';    -- Matches!
... MATCH 'NEAR("a b c d" "b c" "e f", 3)';    -- Does not match!

3.5.FTS5列濾器

單個(gè)短語(yǔ)或NEAR組可能被限制為匹配FTS表的指定列中的文本,方法是將其前綴為列名后跟一個(gè)冒號(hào)字符,?;蛘咴谝唤M列中加上一個(gè)用括號(hào)括起來的空白分隔列表(“花括號(hào)”)后跟一個(gè)冒號(hào)字符作為前綴。列名可以使用上述字符串描述的兩種形式之一來指定,。不像字符串是短語(yǔ)的一部分,,列名不會(huì)傳遞給標(biāo)記器模塊。列名對(duì)于SQLite列名通常不區(qū)分大小寫 - 只對(duì)ASCII范圍字符理解大寫/小寫等價(jià),。

... MATCH 'colname : NEAR("one two" "three four", 10)'
... MATCH '"colname" : one + two + three'

... MATCH '{col1 col2} : NEAR("one two" "three four", 10)'
... MATCH '{col2 col1 col3} : one + two + three'

如果列過濾器規(guī)范前面帶有“ - ”字符,,那么它將被解釋為不匹配列的列表。例如:

-- Search for matches in all columns except "colname"
... MATCH '- colname : NEAR("one two" "three four", 10)'

-- Search for matches in all columns except "col1", "col2" and "col3"
... MATCH '- {col2 col1 col3} : one + two + three'

列過濾器規(guī)格也可以應(yīng)用于括號(hào)內(nèi)的任意表達(dá)式,。在這種情況下,,列過濾器適用于表達(dá)式中的所有短語(yǔ)。嵌套列篩選器操作可能只會(huì)進(jìn)一步限制匹配列的子集,,它們不能用于重新啟用篩選列,。例如:

-- The following are equivalent:
... MATCH '{a b} : ( {b c} : "hello" AND "world" )'
... MATCH '(b : "hello") AND ({a b} : "world")'

最后,可以使用列名作為MATCH運(yùn)算符的LHS(而不是通常的表名)來指定單列的列過濾器,。例如:

-- Given the following table
CREATE VIRTUAL TABLE ft USING fts5(a, b, c);

-- The following are equivalent
SELECT * FROM ft WHERE b MATCH 'uvw AND xyz';
SELECT * FROM ft WHERE ft MATCH 'b : (uvw AND xyz)';

-- This query cannot match any rows (since all columns are filtered out): 
SELECT * FROM ft WHERE b MATCH 'a : xyz';

3.6.FTS5布爾運(yùn)算符

短語(yǔ)和NEAR組可以使用布爾運(yùn)算符排列成表達(dá)式,。按照從最高(最緊密分組)到最低(最寬松分組)的優(yōu)先順序,操作是:

操作者

功能

<query1> NOT <query2>

如果query1匹配且query2不匹配,,則匹配,。

<query1> AND <query2>

如果query1且query2匹配,則匹配,。

<query1> OR <query2>

如果query1或query2匹配,則匹配,。

括號(hào)可用于對(duì)表達(dá)式進(jìn)行分組,,以通常的方式修改運(yùn)算符優(yōu)先級(jí)。例如:

-- Matches documents that contain at least one instance of either "one"
-- or "two", but do not contain any instances of token "three".
... MATCH 'one OR two NOT three'

-- Match all documents that contain the token "two" but not "three", or
-- contain the token "one".
... MATCH 'one OR (two NOT three)'

短語(yǔ)和NEAR組也可以通過隱式AND運(yùn)算符連接,。為了簡(jiǎn)單起見,,這些不在上面的BNF語(yǔ)法中顯示?;旧?,任何短語(yǔ)或NEAR組的序列(包括那些僅限于匹配指定列的短語(yǔ))只能被空格分隔,就好像每對(duì)短語(yǔ)或NEAR組之間存在一個(gè)隱式的AND運(yùn)算符,。隱式AND運(yùn)算符永遠(yuǎn)不會(huì)在括號(hào)內(nèi)的表達(dá)式之前或之后插入,。例如:

... MATCH 'one two three'         -- 'one AND two AND three'
... MATCH 'three "one two"'       -- 'three AND "one two"'
... MATCH 'NEAR(one two) three'   -- 'NEAR(one two) AND three'
... MATCH 'one OR two three'      -- 'one OR two AND three'

... MATCH '(one OR two) three'    -- Syntax error!
... MATCH 'func(one two)'         -- Syntax error!

作為“CREATE VIRTUAL TABLE ... USING fts5 ...”語(yǔ)句的一部分指定的每個(gè)參數(shù)都是列聲明或配置選項(xiàng)。甲列聲明由一個(gè)或多個(gè)空格的分離FTS5裸字或文字串在可接受的SQLite任何方式引用。

列聲明中的第一個(gè)字符串或空白字符是列名稱,。嘗試命名fts5表列“rowid”或“rank”,,或者將相同名稱分配給表本身使用的列是錯(cuò)誤的。這不支持,。

列聲明中的每個(gè)后續(xù)字符串或空白字都是修改該列行為的列選項(xiàng),。列選項(xiàng)與大小寫無關(guān)。與SQLite核心不同,,F(xiàn)TS5將無法識(shí)別的列選項(xiàng)視為錯(cuò)誤,。目前,唯一認(rèn)可的選項(xiàng)是“UNINDEXED”(見下文),。

一個(gè)配置選項(xiàng)包括一個(gè)FTS5裸詞的-選項(xiàng)名稱-后跟一個(gè)“=”字符,,接著是選項(xiàng)值。選項(xiàng)值是使用單個(gè)FTS5空白字符或字符串文字指定的,,再次以SQLite內(nèi)核可接受的任何方式引用,。例如:

CREATE VIRTUAL TABLE mail USING fts5(sender, title, body, tokenize = 'porter ascii');

目前有以下配置選項(xiàng):

  • “tokenize”選項(xiàng),用于配置自定義分詞器,。
  • “prefix”選項(xiàng)用于將前綴索引添加到FTS5表中,。
  • “content”選項(xiàng)用于使FTS5表成為外部?jī)?nèi)容或無內(nèi)容表格。
  • “content_rowid”選項(xiàng)用于設(shè)置外部?jī)?nèi)容表的rowid字段,。
  • “columnsize”選項(xiàng)用于配置FTS5表中每個(gè)值的標(biāo)記大小是否單獨(dú)存儲(chǔ)在數(shù)據(jù)庫(kù)中,。
  • “detail”選項(xiàng)。此選項(xiàng)可用于通過省略某些信息來減小磁盤上FTS索引的大小,。

4.1.UNINDEXED列選項(xiàng)

具有UNINDEXED列選項(xiàng)限定的列的內(nèi)容不會(huì)被添加到FTS索引,。這意味著,出于MATCH查詢和FTS5輔助功能的目的,,該列不包含可匹配的令牌,。

例如,為了避免將“uuid”字段的內(nèi)容添加到FTS索引中:

CREATE VIRTUAL TABLE customers USING fts5(name, addr, uuid UNINDEXED);

4.2.前綴索引

默認(rèn)情況下,,F(xiàn)TS5維護(hù)一個(gè)索引,,記錄每個(gè)令牌實(shí)例在文檔集內(nèi)的位置。這意味著查詢完整令牌的速度很快,,因?yàn)樗恍枰淮尾檎?,但查詢前綴令牌可能會(huì)很慢,因?yàn)樗枰秶鷴呙?。例如,,要查詢前綴標(biāo)記“abc *”,需要對(duì)大于或等于“abc”且小于“abd”的所有標(biāo)記進(jìn)行范圍掃描,。

前綴索引是一個(gè)單獨(dú)的索引,,用于記錄特定長(zhǎng)度的前綴標(biāo)記的所有實(shí)例的位置,,以字符形式用于加速查詢前綴標(biāo)記。例如,,優(yōu)化針對(duì)前綴標(biāo)記“abc *”的查詢需要前綴索引為三個(gè)字符的前綴,。

要將前綴索引添加到FTS5表中,“前綴”選項(xiàng)設(shè)置為單個(gè)正整數(shù)或包含一個(gè)或多個(gè)正整數(shù)值的空格分隔列表的文本值,。為每個(gè)指定的整數(shù)創(chuàng)建一個(gè)前綴索引,。如果多個(gè)“前綴”選項(xiàng)被指定為單個(gè)CREATE VIRTUAL TABLE語(yǔ)句的一部分,則全部適用,。

-- Two ways to create an FTS5 table that maintains prefix indexes for
-- two and three character prefix tokens.
CREATE VIRTUAL TABLE ft USING fts5(a, b, prefix='2 3');
CREATE VIRTUAL TABLE ft USING fts5(a, b, prefix=2, prefix=3);

4.3.斷詞

CREATE VIRTUAL TABLE“tokenize”選項(xiàng)用于配置FTS5表使用的特定標(biāo)記器,。選項(xiàng)參數(shù)必須是FTS5裸字或SQL文本文字。參數(shù)文本本身被視為一個(gè)或多個(gè)FTS5裸字或SQL文本文字的空白系列,。其中第一個(gè)是要使用的標(biāo)記器的名稱,。第二個(gè)和隨后的列表元素(如果存在)是傳遞給標(biāo)記器實(shí)現(xiàn)的參數(shù)。

與選項(xiàng)值和列名不同,,用作標(biāo)記器的SQL文本文字必須使用單引號(hào)字符進(jìn)行引用,。例如:

-- The following are all equivalent
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'porter ascii');
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = "porter ascii");
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = "'porter' 'ascii'");
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = '''porter'' ''ascii''');

-- But this will fail:
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = '"porter" "ascii"');

-- This will fail too:
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'porter' 'ascii');

FTS5具有三個(gè)內(nèi)置的tokenizer模塊,在后面的章節(jié)中有介紹:

  • unicode61標(biāo)記生成器,,基于Unicode 6.1標(biāo)準(zhǔn),。這是默認(rèn)設(shè)置。
  • ASCII標(biāo)記生成器,,其中假設(shè)ASCII碼點(diǎn)范圍(0-127)之外的所有字符都被視為令牌字符,。

也可以為FTS5創(chuàng)建自定義標(biāo)記,。這里描述了這樣做的API。

4.3.1.Unicode61 Tokenizer

unicode標(biāo)記器將所有unicode字符分類為“分隔符”或“標(biāo)記”字符,。默認(rèn)情況下,,Unicode 6.1定義的所有空格和標(biāo)點(diǎn)符號(hào)都被視為分隔符,所有其他字符被視為令牌字符,。每個(gè)連續(xù)運(yùn)行的一個(gè)或多個(gè)令牌字符被視為令牌,。根據(jù)Unicode 6.1定義的規(guī)則,標(biāo)記器不區(qū)分大小寫,。

默認(rèn)情況下,,從所有拉丁腳本字符中刪除了變音符號(hào),。這意味著,,例如,“A”,,“a”,,“à”,“à”,“?”和“a”都被認(rèn)為是等同的,。

令牌規(guī)范中“unicode61”后面的任何參數(shù)都被視為交替選項(xiàng)名稱和值的列表,。Unicode61支持以下選項(xiàng):

選項(xiàng)

用法

remove_diacritics

該選項(xiàng)應(yīng)設(shè)置為“0”或“1”。如果已設(shè)置(默認(rèn)),,則從上述所有拉丁腳本字符中刪除變音符號(hào),。如果很清楚,他們不是,。

tokenchars

此選項(xiàng)用于指定應(yīng)被視為令牌字符的其他Unicode字符,,即使它們是根據(jù)Unicode 6.1的空格或標(biāo)點(diǎn)符號(hào)。該選項(xiàng)設(shè)置為的字符串中的所有字符都被視為令牌字符,。

分離器

此選項(xiàng)用于指定應(yīng)視為分隔符的其他Unicode字符,,即使它們是根據(jù)Unicode 6.1的標(biāo)記字符。該選項(xiàng)設(shè)置為的字符串中的所有字符都被視為分隔符,。

例如:

-- Create an FTS5 table that does not remove diacritics from Latin
-- script characters, and that considers hyphens and underscore characters
-- to be part of tokens. 
CREATE VIRTUAL TABLE ft USING fts5(a, b, 
    tokenize = "unicode61 remove_diacritics 0 tokenchars '-_'"
);

fts5 unicode61標(biāo)記器與fts3 / 4 unicode61標(biāo)記器的字節(jié)對(duì)字節(jié)兼容,。

4.3.2.Ascii Tokenizer

Ascii標(biāo)記器與Unicode61標(biāo)記器類似,不同之處在于:

  • 所有非ASCII字符(代碼點(diǎn)大于127的字符)始終被視為令牌字符,。如果任何非ASCII字符被指定為分隔符選項(xiàng)的一部分,,它們將被忽略。
  • 僅對(duì)ASCII字符執(zhí)行個(gè)案折疊,。所以雖然“A”和“a”被認(rèn)為是等價(jià)的,,但“?”和“?”是不同的。
  • remove_diacritics選項(xiàng)不受支持,。

例如:

-- Create an FTS5 table that uses the ascii tokenizer, but does not
-- consider numeric characters to be part of tokens.
CREATE VIRTUAL TABLE ft USING fts5(a, b, 
    tokenize = "ascii separators '0123456789'"
);

4.3.3.Porter 分詞器

Porter分詞器是一個(gè)包裝分詞器,。它將一些其他分詞器的輸出采用,并在每個(gè)令牌將其返回到FTS5之前將其應(yīng)用到每個(gè)令牌,。這允許諸如“正確”之類的搜索術(shù)語(yǔ)匹配諸如“正確的”或“正確地”之類的類似詞語(yǔ),。porter stemmer算法僅適用于英語(yǔ)語(yǔ)言 - 與其他語(yǔ)言一起使用可能會(huì)或可能不會(huì)提高搜索效用。

默認(rèn)情況下,,porter標(biāo)記器作為默認(rèn)分詞器(unicode61)的包裝器運(yùn)行,。或者,,如果將一個(gè)或多個(gè)額外參數(shù)添加到“porter”后的“tokenize”選項(xiàng)中,,則它們將被視為porter stemmer使用的基礎(chǔ)分詞器的規(guī)范。例如:

-- Two ways to create an FTS5 table that uses the porter tokenizer to
-- stem the output of the default tokenizer (unicode61). 
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = porter); 
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'porter unicode61');

-- A porter tokenizer used to stem the output of the unicode61 tokenizer,
-- with diacritics removed before stemming.
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'porter unicode61 remove_diacritics 1');

4.4.外部?jī)?nèi)容和無內(nèi)容表格

通常,,當(dāng)一行被插入到FTS5表中時(shí),,以及各種全文索引條目和其他數(shù)據(jù),該行的副本被存儲(chǔ)在由FTS5模塊管理的私人表格中,。當(dāng)用戶或輔助功能實(shí)現(xiàn)從FTS5表中請(qǐng)求列值時(shí),,它們將從此專用表中讀取,。“內(nèi)容”選項(xiàng)可用于創(chuàng)建僅存儲(chǔ)FTS全文索引條目的FTS5表,。由于列值本身通常遠(yuǎn)大于關(guān)聯(lián)的全文索引條目,,因此可以節(jié)省大量的數(shù)據(jù)庫(kù)空間。

有兩種方法可以使用“內(nèi)容”選項(xiàng):

  • 通過將其設(shè)置為空字符串來創(chuàng)建無內(nèi)容的FTS5表,。在這種情況下,,F(xiàn)TS5假定處理查詢時(shí)原始列值不可用。全文查詢和一些輔助功能仍然可以使用,,但是除了rowid以外,,沒有列值可以從表中讀取。
  • 通過將其設(shè)置為可隨時(shí)由FTS5查詢的數(shù)據(jù)庫(kù)對(duì)象(表,,虛擬表或視圖)的名稱來檢索列值,。這被稱為“外部?jī)?nèi)容”表。在這種情況下,,可能會(huì)使用所有FTS5功能,,但用戶有責(zé)任確保全文索引的內(nèi)容與指定的數(shù)據(jù)庫(kù)對(duì)象一致。如果不是,,查詢結(jié)果可能不可預(yù)測(cè),。

4.4.1.無內(nèi)容表格

通過將“content”選項(xiàng)設(shè)置為空字符串來創(chuàng)建無內(nèi)容的FTS5表。例如:

CREATE VIRTUAL TABLE f1 USING fts5(a, b, c, content='');

無內(nèi)容FTS5表不支持UPDATE或DELETE語(yǔ)句,,或者不支持rowid字段的非NULL值的INSERT語(yǔ)句,。無內(nèi)容表不支持REPLACE沖突處理。REPLACE和INSERT OR REPLACE語(yǔ)句被視為常規(guī)的INSERT語(yǔ)句,。使用FTS5刪除命令可以從無內(nèi)容表中刪除行,。

嘗試從無內(nèi)容的FTS5表中讀取除rowid以外的任何列值將返回一個(gè)SQL NULL值。

4.4.2.外部?jī)?nèi)容表

通過將內(nèi)容選項(xiàng)設(shè)置為同一數(shù)據(jù)庫(kù)內(nèi)的表,,虛擬表或視圖(以下稱“內(nèi)容表”)的名稱來創(chuàng)建外部?jī)?nèi)容FTS5表,。每當(dāng)FTS5需要列值時(shí),它將按如下方式查詢內(nèi)容表,,將需要值的行的rowid綁定到SQL變量:

SELECT <content_rowid>, <cols> FROM <content> WHERE <content_rowid> = ?;

在上面,,<content>被內(nèi)容表的名稱替換。默認(rèn)情況下,,<content_rowid>由文本文本“rowid”替換,。或者,,如果在CREATE VIRTUAL TABLE語(yǔ)句中設(shè)置了“content_rowid”選項(xiàng),,則按該選項(xiàng)的值設(shè)置。<cols>由FTS5表列名稱的逗號(hào)分隔列表替換,。例如:

-- If the database schema is: 
CREATE TABLE tbl (a, b, c, d INTEGER PRIMARY KEY);
CREATE VIRTUAL TABLE fts USING fts5(a, c, content=tbl, content_rowid=d);

-- Fts5 may issue queries such as:
SELECT d, a, c FROM tbl WHERE d = ?;

內(nèi)容表也可以被查詢?nèi)缦拢?

SELECT <content_rowid>, <cols> FROM <content> ORDER BY <content_rowid> ASC;
SELECT <content_rowid>, <cols> FROM <content> ORDER BY <content_rowid> DESC;

用戶仍然有責(zé)任確保外部?jī)?nèi)容FTS5表的內(nèi)容與內(nèi)容表保持最新,。一種方法是使用觸發(fā)器。例如:

-- Create a table. And an external content fts5 table to index it.
CREATE TABLE tbl(a INTEGER PRIMARY KEY, b, c);
CREATE VIRTUAL TABLE fts_idx USING fts5(b, c, content='tbl', content_rowid='a');

-- Triggers to keep the FTS index up to date.
CREATE TRIGGER tbl_ai AFTER INSERT ON tbl BEGIN
  INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c);
END;
CREATE TRIGGER tbl_ad AFTER DELETE ON tbl BEGIN
  INSERT INTO fts_idx(fts_idx, rowid, b, c) VALUES('delete', old.a, old.b, old.c);
END;
CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN
  INSERT INTO fts_idx(fts_idx, rowid, b, c) VALUES('delete', old.a, old.b, old.c);
  INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c);
END;

像無內(nèi)容表一樣,,外部?jī)?nèi)容表不支持REPLACE沖突處理,。任何指定REPLACE沖突處理的操作都使用ABORT進(jìn)行處理。

4.5.Columnsize選項(xiàng)

通常情況下,,F(xiàn)TS5會(huì)在數(shù)據(jù)庫(kù)中維護(hù)一個(gè)特殊的支持表,,該表將每個(gè)列值的大小存儲(chǔ)在插入到主FTS5表中的令牌的單獨(dú)表中。該支持表由xColumnSize API函數(shù)使用,,該函數(shù)反過來由內(nèi)置的bm25排名函數(shù)使用(并且可能對(duì)其他排名函數(shù)也有用),。

為了節(jié)省空間,可以通過將columnsize選項(xiàng)設(shè)置為零來省略此支持表,。例如:

-- A table without the xColumnSize() values stored on disk:
CREATE VIRTUAL TABLE ft USING fts5(a, b, c, columnsize=0);

-- Three equivalent ways of creating a table that does store the
-- xColumnSize() values on disk:
CREATE VIRTUAL TABLE ft USING fts5(a, b, c);
CREATE VIRTUAL TABLE ft USING fts5(a, b, c, columnsize=1);
CREATE VIRTUAL TABLE ft USING fts5(a, b, columnsize='1', c);

將列大小選項(xiàng)設(shè)置為除0或1以外的任何值都是錯(cuò)誤的,。

如果FTS5表配置為columnsize = 0但不是無內(nèi)容表,則xColumnSize API函數(shù)仍然有效,,但運(yùn)行速度要慢得多,。在這種情況下,不是直接從數(shù)據(jù)庫(kù)中讀取值,,而是讀取文本值本身并根據(jù)需要對(duì)其中的令牌進(jìn)行計(jì)數(shù),。

或者,如果表格也是無內(nèi)容表格,,則適用以下內(nèi)容:

  • xColumnSize API始終返回-1,。無法確定存儲(chǔ)在配置為columnize = 0的無內(nèi)容FTS5表中的值中的令牌數(shù)量。
  • 每個(gè)插入的行必須附有明確指定的rowid值,。如果使用columnsize = 0配置無內(nèi)容表,,則嘗試向rowid中插入NULL值是SQLITE_MISMATCH錯(cuò)誤。
  • 表格上的所有查詢都必須是全文查詢,。換句話說,,他們必須使用MATCH或=操作符和table-name列作為左操作數(shù),否則使用表值函數(shù)語(yǔ)法,。任何不是全文查詢的查詢都會(huì)導(dǎo)致錯(cuò)誤,。存儲(chǔ)xColumnSize值的表的名稱(除非指定了columnsize = 0)是“<name> _docsize”,其中<name>是FTS5表本身的名稱,。該sqlite3_analyzer工具可用于現(xiàn)有數(shù)據(jù)庫(kù),,以便通過使用columnsize = 0重新創(chuàng)建FTS5表來確定可節(jié)省多少空間。4.6,。詳細(xì)選項(xiàng)對(duì)于文檔中的每個(gè)術(shù)語(yǔ),,由FTS5維護(hù)的FTS索引存儲(chǔ)文檔的rowid,包含該術(shù)語(yǔ)的列的列號(hào)以及術(shù)語(yǔ)在列值內(nèi)的偏移量,?!凹?xì)節(jié)”選項(xiàng)可用于省略某些此類信息,。這減少了索引在數(shù)據(jù)庫(kù)文件中占用的空間,但也降低了系統(tǒng)的能力和效率,。詳細(xì)選項(xiàng)可能設(shè)置為“完整”(默認(rèn)值),,“列”或“無”。例如: - 以下兩行相同(因?yàn)椤癲etail”的默認(rèn)值為“full”)CREATE VIRTUAL TABLE ft1使用fts5(a,,b,,C); CREATE VIRTUAL TABLE ft1使用fts5(a,b,,c,,detail = full); 創(chuàng)建虛擬表ft2使用fts5(a,b,,c,,detail = column); CREATE VIRTUAL TABLE ft3使用fts5(a,b,,c,,detail = none);如果detail選項(xiàng)設(shè)置為,那么對(duì)于每個(gè)術(shù)語(yǔ),,F(xiàn)TS索引僅記錄rowid和列號(hào),,省略術(shù)語(yǔ)偏移信息。這會(huì)導(dǎo)致以下限制:
  • NEAR查詢不可用,。
  • 短語(yǔ)查詢不可用,。
  • 假設(shè)表格不是無內(nèi)容表格,則xInstCount,,xInst,,xPhraseFirst和xPraseraseNext比平常慢。這是因?yàn)椴皇侵苯訌腇TS索引中讀取所需的數(shù)據(jù),,而是必須按需加載和標(biāo)記文檔文本,。
  • 如果該表也是無內(nèi)容表,則xInstCount,,xInst,,xPhraseFirst和xPhraseNext API的行為就好像當(dāng)前行根本不包含任何詞組匹配(即xInstCount()返回0)。

如果detail選項(xiàng)設(shè)置為none,,那么對(duì)于每個(gè)術(shù)語(yǔ),,F(xiàn)TS索引只記錄rowid。列和偏移量信息都被省略,。除了上面針對(duì)detail = column模式列出的限制外,,這還會(huì)帶來以下額外限制:

  • 列過濾器查詢不可用。
  • 假設(shè)該表不是一個(gè)無內(nèi)容表,xPhraseFirstColumn和xPhraseNextColumn比平時(shí)慢,。
  • 如果該表也是無內(nèi)容表,,則xPhraseFirstColumn和xPhraseNextColumn API的行為就好像當(dāng)前行根本不包含任何短語(yǔ)匹配(即xPhraseFirstColumn()將迭代器設(shè)置為EOF)。

在一個(gè)對(duì)大量電子郵件進(jìn)行索引的測(cè)試中(磁盤上的1636MBB),,F(xiàn)TS索引在磁盤上為743MB,,其中detail = full,340Mib,,detail = column,134Mib,,detail = none,。

輔助函數(shù)與SQL標(biāo)量函數(shù)類似,但它們只能在FTS5表中的全文查詢(使用MATCH運(yùn)算符的那些查詢)中使用,。他們的結(jié)果不僅根據(jù)傳遞給他們的參數(shù)進(jìn)行計(jì)算,,還會(huì)根據(jù)當(dāng)前匹配和匹配的行進(jìn)行計(jì)算。例如,,輔助函數(shù)可能會(huì)返回一個(gè)表示匹配準(zhǔn)確性的數(shù)值(請(qǐng)參閱bm25()函數(shù)),,或者匹配行中包含搜索項(xiàng)的一個(gè)或多個(gè)實(shí)例的文本片段(請(qǐng)參閱片段( )功能)。

要調(diào)用輔助函數(shù),,應(yīng)將FTS5表的名稱指定為第一個(gè)參數(shù),。其他參數(shù)可以在第一個(gè)之后,具體取決于被調(diào)用的特定輔助功能,。例如,,要調(diào)用“高亮”功能:

SELECT highlight(email, 2, '<b>', '</b>') FROM email WHERE email MATCH 'fts5'

以下部分描述了作為FTS5一部分提供的內(nèi)置輔助功能。應(yīng)用程序也可以在C中實(shí)現(xiàn)定制輔助功能

5.1.內(nèi)置輔助功能

FTS5提供三種內(nèi)置的輔助功能:

  • bm25()輔助函數(shù)返回反映當(dāng)前匹配精度的實(shí)際值,。更好的匹配在數(shù)值上被分配較低的值,。
  • highlight()輔助函數(shù)返回當(dāng)前匹配的一列中的文本的副本,以及由指定標(biāo)記包圍的結(jié)果中的每個(gè)查詢項(xiàng)的實(shí)例(例如“<b>”和“</ b>” ),。
  • snippet()輔助函數(shù)從匹配行的某一列中選擇短文本片段,,并以與highlight()函數(shù)相同的方式返回包含標(biāo)記的查詢術(shù)語(yǔ)的每個(gè)實(shí)例。選擇文本片段以最大化其包含的查詢條目的數(shù)量,。

5.1.1.bm25()函數(shù)

內(nèi)置的輔助函數(shù)bm25()返回一個(gè)實(shí)際值,,表示當(dāng)前行與全文查詢的匹配程度。匹配越好,,返回的數(shù)值越小,。如下所示的查詢可用于按照從最佳匹配到最差匹配的順序返回匹配項(xiàng):

SELECT * FROM fts WHERE fts MATCH ? ORDER BY bm25(fts)

為了計(jì)算文檔分?jǐn)?shù),全文查詢被分成它的組件短語(yǔ),。然后如下計(jì)算文檔D和查詢Q的bm25分?jǐn)?shù):

在上面,,nPhrase是查詢中的短語(yǔ)數(shù)量。| d | 是當(dāng)前文檔中的標(biāo)記數(shù)量,,avgdl是FTS5表格內(nèi)所有文檔中平均標(biāo)記數(shù)量,。k1b都是常數(shù),,分別以1.2和0.75進(jìn)行硬編碼。

公式開始處的“-1”項(xiàng)在BM25算法的大多數(shù)實(shí)現(xiàn)中未找到,。沒有它,,一個(gè)更好的匹配被分配一個(gè)數(shù)值更高的BM25分?jǐn)?shù)。由于默認(rèn)的排序順序是“升序”,,這意味著將“ORDER BY bm25(fts)”附加到查詢會(huì)導(dǎo)致結(jié)果從最壞到最佳順序返回,。為了首先返回最佳匹配,將需要“DESC”關(guān)鍵字,。為了避免這個(gè)陷阱,,BM25的FTS5實(shí)現(xiàn)在返回之前將結(jié)果乘以-1,確保更好的匹配在數(shù)值上被分配較低的分?jǐn)?shù),。

IDF(qi)是查詢短語(yǔ)i的逆文檔頻率,。它計(jì)算如下,其中N是FTS5表中的總行數(shù),,n(qi)是包含至少一個(gè)短語(yǔ)i的實(shí)例的行的總數(shù):

最后,,f(qi,D)是短語(yǔ)i的短語(yǔ)頻率,。默認(rèn)情況下,,這僅僅是當(dāng)前行內(nèi)短語(yǔ)的出現(xiàn)次數(shù)。但是,,通過向bm25()SQL函數(shù)傳遞額外的實(shí)參值,,可以為表的每列分配不同的權(quán)重,并按如下方式計(jì)算短語(yǔ)頻率:

其中wc是分配給c列的權(quán)重,,n(qi,,c)是當(dāng)前行的c列中詞組i的出現(xiàn)次數(shù)。傳遞給表名后面的bm25()的第一個(gè)參數(shù)是分配給FTS5表最左列的權(quán)重,。第二個(gè)是分配給第二個(gè)最左列的權(quán)重,,依此類推。如果沒有足夠的參數(shù)用于所有表格列,,則為其余列指定1.0的權(quán)重,。如果后面的參數(shù)太多,則會(huì)忽略額外值,。例如:

-- Assuming the following schema:
CREATE VIRTUAL TABLE email USING fts5(sender, title, body);

-- Return results in bm25 order, with each phrase hit in the "sender"
-- column considered the equal of 10 hits in the "body" column, and
-- each hit in the "title" column considered as valuable as 5 hits in
-- the "body" column.
SELECT * FROM email WHERE email MATCH ? ORDER BY bm25(email, 10.0, 5.0);

有關(guān)BM25及其變體的更多信息,,請(qǐng)參閱維基百科。

5.1.2.highlight()函數(shù)

highlight()函數(shù)返回當(dāng)前行指定列中文本的副本,,并插入額外的標(biāo)記文本以標(biāo)記詞組匹配的開始和結(jié)束,。

必須使用表名后面的三個(gè)參數(shù)調(diào)用highlight()。解釋如下:

  1. 一個(gè)整數(shù),指示要從中讀取文本的FTS表列的索引,。列從零開始從左到右進(jìn)行編號(hào),。

2. 在每個(gè)詞組匹配前插入的文本。

3. 在每個(gè)詞組匹配后插入的文本,。

例如:

-- Return a copy of the text from the leftmost column of the current
-- row, with phrase matches marked using html "b" tags.
SELECT highlight(fts, 0, '<b>', '</b>') FROM fts WHERE fts MATCH ?

在兩個(gè)或兩個(gè)以上短語(yǔ)實(shí)例重疊(共享一個(gè)或多個(gè)標(biāo)記)的情況下,,為每組重疊短語(yǔ)插入單個(gè)打開和關(guān)閉標(biāo)記。例如:

-- Assuming this:
CREATE VIRTUAL TABLE ft USING fts5(a);
INSERT INTO ft VALUES('a b c x c d e');
INSERT INTO ft VALUES('a b c c d e');
INSERT INTO ft VALUES('a b c d e');

-- The following SELECT statement returns these three rows:
--   '[a b c] x [c d e]'
--   '[a b c] [c d e]'
--   '[a b c d e]'
SELECT highlight(ft, 0, '[', ']') FROM ft WHERE ft MATCH 'a+b+c AND c+d+e';

5.1.3.snippet()函數(shù)

snippet()函數(shù)與highlight()類似,,不同之處在于它不是返回整個(gè)列值,,而是自動(dòng)選擇并提取文檔文本的短片段以進(jìn)行處理和返回。snippet()函數(shù)必須在表名參數(shù)之后傳遞五個(gè)參數(shù):

  1. 一個(gè)整數(shù),,指示從中選擇返回文本的FTS表列的索引,。列從零開始從左到右進(jìn)行編號(hào)。負(fù)值表示應(yīng)該自動(dòng)選擇該列,。

2. 要在返回的文本中匹配每個(gè)詞組之前插入的文本,。

3. 要在返回的文本中匹配每個(gè)詞組之后插入的文本,。

4. 要添加到選定文本的開頭或結(jié)尾的文本,,以分別指示返回的文本不會(huì)在其列的開頭或結(jié)尾出現(xiàn)。

5. 返回文本中令牌的最大數(shù)量,。這必須大于零并且等于或小于64,。

5.2.通過輔助功能結(jié)果排序

所有FTS5表格都有一個(gè)名為“rank”的特殊隱藏欄。如果當(dāng)前查詢不是全文查詢(即,,如果它不包含MATCH運(yùn)算符),,則“rank”列的值始終為NULL。否則,,在全文查詢中,,列等級(jí)默認(rèn)包含與通過執(zhí)行沒有結(jié)尾參數(shù)的bm25()輔助函數(shù)返回的值相同的值。

從排序列讀取和直接在查詢中使用bm25()函數(shù)之間的差異僅在通過返回值進(jìn)行排序時(shí)顯著,。在這種情況下,,使用“rank”比使用bm25()更快。

-- The following queries are logically equivalent. But the second may
-- be faster, particularly if the caller abandons the query before
-- all rows have been returned (or if the queries were modified to 
-- include LIMIT clauses).
SELECT * FROM fts WHERE fts MATCH ? ORDER BY bm25(fts);
SELECT * FROM fts WHERE fts MATCH ? ORDER BY rank;

不使用bm25()而不使用尾隨參數(shù),,映射到rank列的特定輔助函數(shù)可以基于每個(gè)查詢進(jìn)行配置,,也可以通過為FTS表設(shè)置不同的持久性默認(rèn)值來進(jìn)行配置。

為了更改單個(gè)查詢的排列列的映射,,將類似于以下任一項(xiàng)的術(shù)語(yǔ)添加到查詢的WHERE子句中:

rank MATCH 'auxiliary-function-name(arg1, arg2, ...)'
rank = 'auxiliary-function-name(arg1, arg2, ...)'

MATCH或=運(yùn)算符的右側(cè)必須是一個(gè)常量表達(dá)式,,該表達(dá)式的結(jié)果是由要調(diào)用的輔助函數(shù)組成的字符串,然后是括號(hào)內(nèi)的零個(gè)或多個(gè)以逗號(hào)分隔的參數(shù),。參數(shù)必須是SQL文字,。例如:

-- The following queries are logically equivalent. But the second may
-- be faster. See above. 
SELECT * FROM fts WHERE fts MATCH ? ORDER BY bm25(fts, 10.0, 5.0);
SELECT * FROM fts WHERE fts MATCH ? AND rank MATCH 'bm25(10.0, 5.0)' ORDER BY rank;

表值函數(shù)語(yǔ)法也可以用于指定替代的排名函數(shù)。在這種情況下,應(yīng)該將描述排名函數(shù)的文本指定為第二個(gè)表值函數(shù)參數(shù),。以下三個(gè)查詢是等價(jià)的:

SELECT * FROM fts WHERE fts MATCH ? AND rank MATCH 'bm25(10.0, 5.0)' ORDER BY rank;
SELECT * FROM fts WHERE fts = ? AND rank = 'bm25(10.0, 5.0)' ORDER BY rank;
SELECT * FROM fts WHERE fts(?, 'bm25(10.0, 5.0)') ORDER BY rank;

可以使用FTS5等級(jí)配置選項(xiàng)來修改表的等級(jí)列的默認(rèn)映射,。

6.1.'automerge'配置選項(xiàng)

FTS5不是使用磁盤上的單個(gè)數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ)全文索引,而是使用一系列b-樹,。每次提交新事務(wù)時(shí),,都會(huì)將包含已提交事務(wù)內(nèi)容的新b-樹寫入數(shù)據(jù)庫(kù)文件。查詢?nèi)乃饕龝r(shí),,必須單獨(dú)查詢每棵b樹,,并在返回給用戶之前合并結(jié)果。

為了防止數(shù)據(jù)庫(kù)中b樹的數(shù)量變得過大(減慢查詢速度),,將較小的b樹周期性地合并為包含相同數(shù)據(jù)的單個(gè)較大的b樹,。默認(rèn)情況下,這會(huì)在修改全文索引的INSERT,,UPDATE或DELETE語(yǔ)句中自動(dòng)發(fā)生,。'automerge'參數(shù)確定一次有多少個(gè)小型b-樹合并在一起。將它設(shè)置為一個(gè)較小的值可以加快查詢速度(因?yàn)樗鼈儽仨毑樵兒秃喜碜暂^少b-樹的結(jié)果),,但是也會(huì)減慢對(duì)數(shù)據(jù)庫(kù)的寫入速度(因?yàn)槊總€(gè)INSERT,,UPDATE或DELETE語(yǔ)句都需要做更多的工作作為自動(dòng)合并過程的一部分)。

構(gòu)成全文索引的每個(gè)b樹被分配到基于其大小的“級(jí)別”,。0級(jí)b樹是最小的,,因?yàn)樗鼈儼瑔蝹€(gè)事務(wù)的內(nèi)容。更高級(jí)的b樹是將兩個(gè)或更多的0級(jí)b樹合并在一起的結(jié)果,,因此它們更大,。一旦存在M個(gè)或更多具有相同級(jí)別的b樹,F(xiàn)TS5開始將b樹合并在一起,,其中M是'automerge'參數(shù)的值,。

“automerge”參數(shù)的最大允許值為16.默認(rèn)值為4.將'automerge'參數(shù)設(shè)置為0將禁用b樹的自動(dòng)增量合并。

INSERT INTO ft(ft, rank) VALUES('automerge', 8);

6.2.'危機(jī)綜合'配置選項(xiàng)

'危機(jī)合并'選項(xiàng)與'automerge'類似,,因?yàn)樗鼪Q定了組成全文索引的組件B樹如何以及經(jīng)常合并到一起,。一旦全文索引中的單一級(jí)別存在C或更多的B樹,其中C是“危機(jī)合并”選項(xiàng)的值,,則該級(jí)別上的所有B樹都會(huì)立即合并為一棵B樹,。

此選項(xiàng)和“automerge”選項(xiàng)之間的區(qū)別在于,當(dāng)達(dá)到“automerge”限制時(shí),,F(xiàn)TS5僅開始將b樹合并在一起,。大部分工作是作為后續(xù)INSERT,UPDATE或DELETE操作的一部分執(zhí)行的,。而當(dāng)達(dá)到“危機(jī)醞釀”的限制時(shí),,違規(guī)的B樹就會(huì)立即合并,。這意味著觸發(fā)危機(jī)合并的INSERT,UPDATE或DELETE可能需要很長(zhǎng)時(shí)間才能完成,。

默認(rèn)的“危機(jī)匯編”值為16.沒有最大限制,。嘗試將'crisismerge'參數(shù)設(shè)置為0或1的值相當(dāng)于將其設(shè)置為默認(rèn)值(16)。試圖將“危機(jī)合并”選項(xiàng)設(shè)置為負(fù)值是錯(cuò)誤的,。

INSERT INTO ft(ft, rank) VALUES('crisismerge', 16);

6.3.'刪除'命令

此命令僅適用于外部?jī)?nèi)容和無內(nèi)容表,。它用于從全文索引中刪除與單個(gè)行關(guān)聯(lián)的索引條目。此命令和delete-all命令是從無內(nèi)容表的全文索引中刪除條目的唯一方法,。

為了使用此命令刪除一行,,必須將文本值'delete'插入與該表名稱相同的特殊列中。要?jiǎng)h除的行的rowid插入到rowid列中,。插入到其他列中的值必須與當(dāng)前存儲(chǔ)在表中的值匹配,。例如:

-- Insert a row with rowid=14 into the fts5 table.
INSERT INTO ft(rowid, a, b, c) VALUES(14, $a, $b, $c);

-- Remove the same row from the fts5 table.
INSERT INTO ft(ft, rowid, a, b, c) VALUES('delete', 14, $a, $b, $c);

如果作為“刪除”命令的一部分“插入”文本列的值與當(dāng)前存儲(chǔ)在表中的值不同,則結(jié)果可能不可預(yù)知,。

原因很容易理解:將文檔插入到FTS5表中時(shí),,將向全文索引添加一個(gè)條目,以記錄每個(gè)令牌在新文檔中的位置,。刪除文檔時(shí),,需要原始數(shù)據(jù)以確定需要從全文索引中刪除的一組條目。因此,,如果使用此命令刪除一行時(shí)提供給FTS5的數(shù)據(jù)與插入時(shí)用于確定該令牌實(shí)例集的數(shù)據(jù)不同,,則某些全文索引條目可能無法正確刪除,,或者FTS5可能會(huì)嘗試刪除索引條目不存在,。這會(huì)使全文索引處于不可預(yù)知的狀態(tài),使得將來的查詢結(jié)果不可靠,。

6.4.'全部刪除'命令

此命令僅適用于外部?jī)?nèi)容和無內(nèi)容表,。它從全文索引中刪除所有條目。

INSERT INTO ft(ft) VALUES('delete-all');

6.5.'完整性檢查'命令

該命令用于驗(yàn)證全文索引是否與FTS5表或內(nèi)容表的內(nèi)容一致,。它不適用于無內(nèi)容表格,。

通過將文本值'integrity-check'插入到與FTS5表同名的特殊列中來調(diào)用integrity-check命令。例如:

INSERT INTO ft(ft) VALUES('integrity-check');

如果全文索引與表的內(nèi)容一致,,則用于調(diào)用integrity-check命令的INSERT成功,。或者,,如果發(fā)現(xiàn)任何差異,,則會(huì)失敗并顯示SQLITE_CORRUPT_VTAB錯(cuò)誤。

6.6.'合并'命令

INSERT INTO ft(ft, rank) VALUES('merge', 500);

該命令將b-樹結(jié)構(gòu)合并到一起,,直到大約N頁(yè)的合并數(shù)據(jù)被寫入數(shù)據(jù)庫(kù),,其中N是作為“合并”命令的一部分指定的參數(shù)的絕對(duì)值,。每個(gè)頁(yè)面的大小由FTS5 pgsz選項(xiàng)配置。

如果參數(shù)是正值,,則只有滿足以下條件之一時(shí),,B樹結(jié)構(gòu)才有資格進(jìn)行合并:

  • 在單個(gè)級(jí)別上有多個(gè)或多個(gè)這樣的b樹(有關(guān)b樹級(jí)別的解釋,請(qǐng)參閱FTS5 automerge選項(xiàng)的文檔),,其中U是分配給FTS5 usermerge選項(xiàng)選項(xiàng)的值,。
  • 合并已經(jīng)開始(可能通過指定否定參數(shù)的“合并”命令)。

通過在命令執(zhí)行前后檢查sqlite3_total_changes()API返回的值,,可以判斷'merge'命令是否找到任何b-tree合并在一起,。如果兩個(gè)值之間的差值是2或更大,則執(zhí)行工作,。如果差值小于2,,那么'合并'命令是無操作的。在這種情況下,,沒有理由再次執(zhí)行相同的“合并”命令,,至少在下一次更新FTS表之后。

如果參數(shù)為負(fù)數(shù),,并且在FTS索引內(nèi)的多個(gè)級(jí)別上有B樹結(jié)構(gòu),,則在開始合并操作之前,將所有B樹結(jié)構(gòu)分配到同一級(jí)別,。此外,,如果參數(shù)為負(fù)數(shù),則不會(huì)考慮usermerge配置選項(xiàng)的值 - 只要來自同一級(jí)別的兩棵b樹可以合并在一起即可,。

上面的意思是執(zhí)行帶有負(fù)參數(shù)的'merge'命令,,直到sqlite3_total_changes()的返回值的前后差小于2,以與FTS5優(yōu)化命令相同的方式優(yōu)化FTS索引,。但是,,如果在此過程正在進(jìn)行時(shí)將新的b-tree添加到FTS索引,則FTS5會(huì)將新的b-tree移至與現(xiàn)有b-樹相同的級(jí)別并重新開始合并,。為了避免這種情況,,只有第一次調(diào)用'合并'應(yīng)該指定一個(gè)負(fù)參數(shù)。每次后續(xù)對(duì)“合并”的調(diào)用都應(yīng)該指定一個(gè)正值,,以便即使將新的b樹添加到FTS索引中,,第一次調(diào)用所啟動(dòng)的合并也會(huì)運(yùn)行到完成狀態(tài)。

6.7.'優(yōu)化'命令

該命令將當(dāng)前構(gòu)成全文索引的所有單個(gè)b樹合并為一個(gè)大的b樹結(jié)構(gòu),。這可確保全文索引消耗數(shù)據(jù)庫(kù)中的最小空間,,并以最快的形式進(jìn)行查詢。

有關(guān)全文索引及其組件b-trees之間關(guān)系的更多詳細(xì)信息,,請(qǐng)參閱FTS5 automerge選項(xiàng)的文檔,。

INSERT INTO ft(ft) VALUES('optimize');

因?yàn)樗匦陆M織整個(gè)FTS索引,,所以優(yōu)化命令可能需要很長(zhǎng)時(shí)間才能運(yùn)行。FTS5合并命令可用于將優(yōu)化FTS索引的工作劃分為多個(gè)步驟,。去做這個(gè):

  • 然后調(diào)用參數(shù)設(shè)置為-N的“merge”命令一次
  • 將參數(shù)設(shè)置為N,,調(diào)用“合并”命令零次或多次

其中N是每次合并命令調(diào)用時(shí)要合并的數(shù)據(jù)頁(yè)數(shù)。當(dāng)合并命令前后sqlite3_total_changes()函數(shù)返回的值的差異降至2以下時(shí),,應(yīng)用程序應(yīng)停止調(diào)用合并,。合并命令可以作為相同或單獨(dú)事務(wù)的一部分以及由相同或不同數(shù)據(jù)庫(kù)客戶機(jī)發(fā)出。有關(guān)更多詳細(xì)信息,,請(qǐng)參閱合并命令的文檔,。

6.8.'pgsz'配置選項(xiàng)

該命令用于設(shè)置持久性“pgsz”選項(xiàng)。

由FTS5維護(hù)的全文索引作為一系列固定大小的斑點(diǎn)存儲(chǔ)在數(shù)據(jù)庫(kù)表中,。構(gòu)成全文索引的所有斑點(diǎn)的大小并不是完全必要的,。pgsz選項(xiàng)決定后續(xù)索引編寫者創(chuàng)建的所有斑點(diǎn)的大小。缺省值是1000,。

INSERT INTO ft(ft, rank) VALUES('pgsz', 4072);

6.9.'等級(jí)'配置選項(xiàng)

該命令用于設(shè)置持久“排序”選項(xiàng),。

rank選項(xiàng)用于更改rank列的默認(rèn)輔助功能映射。該選項(xiàng)應(yīng)設(shè)置為與“等級(jí)匹配”所描述的格式相同的文本值,。上述條款,。例如:

INSERT INTO ft(ft, rank) VALUES('rank', 'bm25(10.0, 5.0)');

6.10.'重建'命令

該命令首先刪除整個(gè)全文索引,然后根據(jù)表或內(nèi)容表的內(nèi)容重建它,。它不適用于無內(nèi)容表格,。

INSERT INTO ft(ft) VALUES('rebuild');

6.11.'usermerge'配置選項(xiàng)

該命令用于設(shè)置持久的“用戶合并”選項(xiàng)。

usermerge選項(xiàng)類似于automerge和crisismerge選項(xiàng),。它是通過具有正參數(shù)的“合并”命令合并在一起的最小數(shù)量的b-樹段。例如:

INSERT INTO ft(ft, rank) VALUES('usermerge', 4);

usermerge選項(xiàng)的默認(rèn)值為4.允許的最小值為2,,最大值為16,。

FTS5具有API,可通過以下方式進(jìn)行擴(kuò)展:

  • 添加在C中實(shí)現(xiàn)的新輔助功能,,以及
  • 添加新的標(biāo)記器,,也在C中實(shí)現(xiàn)。

本文檔中描述的內(nèi)置令牌處理器和輔助功能都是使用下面描述的公共可用API實(shí)現(xiàn)的,。

在向FTS5注冊(cè)新的輔助函數(shù)或標(biāo)記器實(shí)現(xiàn)之前,,應(yīng)用程序必須獲得指向“fts5_api”結(jié)構(gòu)的指針。每個(gè)與FTS5擴(kuò)展注冊(cè)的數(shù)據(jù)庫(kù)連接都有一個(gè)fts5_api結(jié)構(gòu),。為了獲得指針,,應(yīng)用程序用一個(gè)參數(shù)調(diào)用SQL用戶定義函數(shù)fts5(),。必須使用sqlite3_bind_pointer()接口將該參數(shù)設(shè)置為指向指向fts5_api對(duì)象的指針。以下示例代碼演示了該技術(shù):

/*
** Return a pointer to the fts5_api pointer for database connection db.
** If an error occurs, return NULL and leave an error in the database 
** handle (accessible using sqlite3_errcode()/errmsg()).
*/
fts5_api *fts5_api_from_db(sqlite3 *db){
  fts5_api *pRet = 0;
  sqlite3_stmt *pStmt = 0;

  if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0) ){
    sqlite3_bind_pointer(pStmt, (void*)&pRet, "fts5_api_ptr", NULL);
    sqlite3_step(pStmt);
  }
  sqlite3_finalize(pStmt);
  return pRet;
}

向后兼容性警告:在SQLite版本3.20.0(2017-08-01)之前,,fts5()的工作方式稍有不同,。擴(kuò)展FTS5的舊版應(yīng)用程序必須修改為使用上述新技術(shù)。

fts5_api結(jié)構(gòu)定義如下,。它公開了三種方法,,一種用于注冊(cè)新的輔助功能和標(biāo)記器,另一種用于檢索現(xiàn)有的標(biāo)記器,。后者旨在促進(jìn)類似于內(nèi)置的porter tokenizer的“tokenizer包裝器”的實(shí)現(xiàn),。

typedef struct fts5_api fts5_api;
struct fts5_api {
  int iVersion;                   /* Currently always set to 2 */

  /* Create a new tokenizer */
  int (*xCreateTokenizer)(
    fts5_api *pApi,
    const char *zName,
    void *pContext,
    fts5_tokenizer *pTokenizer,
    void (*xDestroy)(void*)
  );

  /* Find an existing tokenizer */
  int (*xFindTokenizer)(
    fts5_api *pApi,
    const char *zName,
    void **ppContext,
    fts5_tokenizer *pTokenizer
  );

  /* Create a new auxiliary function */
  int (*xCreateFunction)(
    fts5_api *pApi,
    const char *zName,
    void *pContext,
    fts5_extension_function xFunction,
    void (*xDestroy)(void*)
  );
};

為了調(diào)用fts5_api對(duì)象的方法,應(yīng)該將fts5_api指針本身作為方法第一個(gè)參數(shù)傳遞,,然后傳遞其他方法特定的參數(shù),。例如:

rc = pFts5Api->xCreateTokenizer(pFts5Api, ... other args ...);

以下各節(jié)分別介紹fts5_api結(jié)構(gòu)方法。

7.1.自定義標(biāo)志符

要?jiǎng)?chuàng)建自定義標(biāo)記器,,應(yīng)用程序必須實(shí)現(xiàn)三個(gè)函數(shù):標(biāo)記器構(gòu)造函數(shù)(xCreate),,析構(gòu)函數(shù)(xDelete)和執(zhí)行實(shí)際標(biāo)記化(xTokenize)的函數(shù)。每個(gè)函數(shù)的類型與fts5_tokenizer結(jié)構(gòu)的成員變量相同:

typedef struct Fts5Tokenizer Fts5Tokenizer;
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
  void (*xDelete)(Fts5Tokenizer*);
  int (*xTokenize)(Fts5Tokenizer*, 
      void *pCtx,
      int flags,            /* Mask of FTS5_TOKENIZE_* flags */
      const char *pText, int nText, 
      int (*xToken)(
        void *pCtx,         /* Copy of 2nd argument to xTokenize() */
        int tflags,         /* Mask of FTS5_TOKEN_* flags */
        const char *pToken, /* Pointer to buffer containing token */
        int nToken,         /* Size of token in bytes */
        int iStart,         /* Byte offset of token within input text */
        int iEnd            /* Byte offset of end of token within input text */
      )
  );
};

/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY     0x0001
#define FTS5_TOKENIZE_PREFIX    0x0002
#define FTS5_TOKENIZE_DOCUMENT  0x0004
#define FTS5_TOKENIZE_AUX       0x0008

/* Flags that may be passed by the tokenizer implementation back to FTS5
** as the third argument to the supplied xToken callback. */
#define FTS5_TOKEN_COLOCATED    0x0001      /* Same position as prev. token */

當(dāng)FTS5表使用自定義標(biāo)記器時(shí),,F(xiàn)TS5內(nèi)核調(diào)用xCreate()一次創(chuàng)建標(biāo)記器,,然后xTokenize()零次或多次標(biāo)記字符串,然后使用xDelete()釋放由xCreate()分配的任何資源,。進(jìn)一步來說:

xCreate:

該函數(shù)用于分配和初始化標(biāo)記器實(shí)例,。標(biāo)記器實(shí)例需要實(shí)際標(biāo)記文本。

傳遞給此函數(shù)的第一個(gè)參數(shù)是當(dāng)fts5_tokenizer對(duì)象使用FTS5(xCreateTokenizer()的第三個(gè)參數(shù))注冊(cè)時(shí),,應(yīng)用程序提供的(void *)指針的副本,。第二個(gè)和第三個(gè)參數(shù)是一個(gè)由nul結(jié)尾的字符串組成的數(shù)組,包含標(biāo)記器參數(shù)(如果有),,作為用于創(chuàng)建FTS5表的CREATE VIRTUAL TABLE語(yǔ)句的一部分,,在標(biāo)記器名稱后指定。

最后一個(gè)參數(shù)是一個(gè)輸出變量,。如果成功,,應(yīng)將(* ppOut)設(shè)置為指向新的標(biāo)記器句柄并返回SQLITE_OK。如果發(fā)生錯(cuò)誤,,則應(yīng)返回SQLITE_OK以外的值,。在這種情況下,fts5假定* ppOut的最終值未定義,。

xDelete:

調(diào)用此函數(shù)以刪除先前使用xCreate()分配的標(biāo)記器句柄,。Fts5保證每次成功調(diào)用xCreate()時(shí)都會(huì)調(diào)用該函數(shù)一次。

xTokenize:

這個(gè)函數(shù)預(yù)計(jì)會(huì)標(biāo)記由參數(shù)pText指示的nText字節(jié)字符串,。pText可能會(huì)或可能不會(huì)被終止,。傳遞給此函數(shù)的第一個(gè)參數(shù)是一個(gè)指向先前調(diào)用xCreate()所返回的Fts5Tokenizer對(duì)象的指針。

第二個(gè)參數(shù)表明FTS5正在請(qǐng)求提供文本的標(biāo)記的原因,。這總是以下四個(gè)值之一:

  • FTS5_TOKENIZE_DOCUMENT - 正在將文檔插入FTS表中或從中刪除。正在調(diào)用標(biāo)記器以確定要添加到(或從中刪除)FTS索引的標(biāo)記集,。
  • FTS5_TOKENIZE_QUERY - MATCH查詢正在針對(duì)FTS索引執(zhí)行,。正在調(diào)用標(biāo)記器來標(biāo)記指定為查詢一部分的裸字或帶引號(hào)的字符串。
  • (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - 與FTS5_TOKENIZE_QUERY相同,,不同之處在于裸詞或帶引號(hào)的字符串后跟“*”字符,,表示標(biāo)記器返回的最后一個(gè)標(biāo)記將被視為標(biāo)記前綴。
  • FTS5_TOKENIZE_AUX - 正在調(diào)用標(biāo)記器以滿足輔助函數(shù)所做的fts5_api.xTokenize()請(qǐng)求,?;蛘咴赾olumnize = 0的數(shù)據(jù)庫(kù)上使用相同的fts5_api.xColumnSize()請(qǐng)求。

對(duì)于輸入字符串中的每個(gè)標(biāo)記,,必須調(diào)用提供的回調(diào)xToken(),。它的第一個(gè)參數(shù)應(yīng)該是作為xTokenize()的第二個(gè)參數(shù)傳遞的指針的副本。第三和第四個(gè)參數(shù)是指向包含標(biāo)記文本的緩沖區(qū)的指針,,以及以字節(jié)為單位的標(biāo)記大小。第四個(gè)和第五個(gè)參數(shù)是緊接在輸入中衍生出令牌的文本之后的第一個(gè)字節(jié)和第一個(gè)字節(jié)的字節(jié)偏移量,。

傳遞給xToken()回調(diào)(“tflags”)的第二個(gè)參數(shù)通常應(yīng)設(shè)置為0.例外是,如果標(biāo)記器支持同義詞,。在這種情況下,請(qǐng)參閱下面的討論了解詳情,。

FTS5假定xToken()回調(diào)是按照它們?cè)谳斎胛谋局谐霈F(xiàn)的順序?yàn)槊總€(gè)令牌調(diào)用的。

如果xToken()回調(diào)函數(shù)返回除SQLITE_OK以外的任何值,,則應(yīng)放棄標(biāo)記化處理,,并且xTokenize()方法應(yīng)立即返回xToken()返回值的副本?;蛘?,如果輸入緩沖區(qū)耗盡,,xTokenize()應(yīng)返回SQLITE_OK,。最后,如果xTokenize()實(shí)現(xiàn)本身發(fā)生錯(cuò)誤,,它可能會(huì)放棄標(biāo)記并返回除SQLITE_OK或SQLITE_DONE以外的任何錯(cuò)誤代碼,。

7.1.1.同義詞支持

自定義標(biāo)記器也可能支持同義詞,??紤]用戶希望查詢諸如“首位”之類的短語(yǔ)的情況,。使用內(nèi)置的分詞器,,F(xiàn)TS5查詢“first + place”將匹配文檔集內(nèi)“first place”的實(shí)例,但不能替代“first place”等其他形式。在某些應(yīng)用程序中,,最好匹配“第一位”或“第一位”的所有實(shí)例,無論MATCH查詢文本中指定的用戶是哪一種形式,。

在FTS5中有幾種方法可以解決這個(gè)問題:

  1. 通過將所有同義詞映射到單個(gè)令牌,。在這種情況下,,在上面的例子中,,這意味著標(biāo)記器為輸入“first”和“1st”返回相同的標(biāo)記。說令牌實(shí)際上是“第一”,,這樣當(dāng)用戶插入文件“我贏了第一名”時(shí),,條目將被添加到令牌“我”,“贏”,,“第一”和“地點(diǎn)”的索引中,。如果用戶然后查詢“1st + place”,則標(biāo)記器將“first”替換為“1st”,,并且查詢按預(yù)期工作,。
  1. 通過為FTS索引添加單個(gè)詞語(yǔ)的多個(gè)同義詞。在這種情況下,,當(dāng)標(biāo)記化查詢文本時(shí),,標(biāo)記器可以為文檔中的單個(gè)詞提供多個(gè)同義詞,。然后FTS5分別查詢每個(gè)同義詞的索引,。例如,,面對(duì)查詢:... MATCH'第一名'

標(biāo)記器同時(shí)為MATCH查詢中的第一個(gè)標(biāo)記提供“1st”和“first”作為同義詞,F(xiàn)TS5有效地運(yùn)行類似于以下內(nèi)容的查詢:

... MATCH '(first OR 1st) place'

除了為了輔助功能的目的,,查詢?nèi)匀话瑑蓚€(gè)短語(yǔ) - “(first OR 1st)”被視為單個(gè)短語(yǔ),。

  1. 通過為FTS索引添加單個(gè)詞語(yǔ)的多個(gè)同義詞。使用此方法時(shí),,標(biāo)記文檔文本時(shí),,標(biāo)記器為每個(gè)標(biāo)記提供多個(gè)同義詞。因此,,當(dāng)諸如“我贏了第一名”之類的文檔被標(biāo)記時(shí),,條目將被添加到“我”,“贏”,,“第一”,,“第一”和“地點(diǎn)”的FTS索引,。這樣,,即使標(biāo)記器在標(biāo)記查詢文本時(shí)不提供同義詞(它不應(yīng)該 - 這樣做效率不高),如果用戶查詢“first + place”或“1st + place”,則無關(guān)緊要,,因?yàn)樵贔TS索引中存在與第一令牌的兩種形式相對(duì)應(yīng)的實(shí)體,。無論是解析文檔還是查詢文本,,對(duì)xToken的任何調(diào)用都會(huì)指定一個(gè)tflags與FTS5_TOKEN_COLOCATED位的參數(shù)被認(rèn)為是為前一個(gè)標(biāo)記提供同義詞,。例如,,當(dāng)解析文檔“我贏了第一名”時(shí),,支持同義詞的分詞器將調(diào)用xToken()5次,如下所示:xToken(pCtx,,0,,“i”,1,0,1); xToken(pCtx,,0,“won”,,3,2,,5); xToken(pCtx,0,,“first”,,5,6,11); xToken(pCtx,F(xiàn)TS5_TOKEN_COLOCATED,“1st”,3,,6,,11); xToken(pCtx,0,,“place”,5,12,17); 第一次調(diào)用xToken()時(shí)指定FTS5_TOKEN_COLOCATED標(biāo)志是錯(cuò)誤的。通過依次對(duì)xToken(FTS5_TOKEN_COLOCATED)進(jìn)行多次調(diào)用,可以為單個(gè)標(biāo)記指定多個(gè)同義詞??梢詾閱蝹€(gè)令牌提供的同義詞數(shù)量沒有限制。在許多情況下,,上述方法(1)是最好的方法,。它不會(huì)將額外的數(shù)據(jù)添加到FTS索引或要求FTS5查詢多個(gè)術(shù)語(yǔ),因此它在磁盤空間和查詢速度方面效率很高,。但是,,它不能很好地支持前綴查詢。如果如上所述,,令牌“第一”被標(biāo)記器取代為“1st”,,則查詢:... MATCH'1s *'將不匹配包含標(biāo)記“1st”的文檔(因?yàn)闃?biāo)記器可能不將“1”映射到任何前綴“第一”)。對(duì)于完整的前綴支持,,方法(3)可能是首選,。在這種情況下,因?yàn)樗饕癴irst”和“1st”的條目,,所以前綴查詢(如'fi *'或'1s *' 將正確匹配,。但是,,由于額外的條目被添加到FTS索引,此方法在數(shù)據(jù)庫(kù)中使用更多的空間,。方法(2)提供(1)和(3)之間的中點(diǎn),。使用這種方法,諸如'1s *'的查詢將匹配包含文字標(biāo)記“1st”但不是“first”的文檔(假設(shè)標(biāo)記器不能提供前綴的同義詞),。但是,,像'1st'這樣的非前綴查詢將匹配“1st”和“first”。此方法不需要額外的磁盤空間,,因?yàn)闆]有額外的條目添加到FTS索引,。另一方面,它可能需要更多CPU周期來運(yùn)行MATCH查詢,,因?yàn)槊總€(gè)同義詞需要單獨(dú)的FTS索引查詢,。當(dāng)使用方法(2)或(3)時(shí),記號(hào)器僅在標(biāo)記文檔文本(方法(2))或查詢文本(方法(3))時(shí)提供同義詞,,而非兩者都是非常重要的,。這樣做不會(huì)導(dǎo)致任何錯(cuò)誤,但效率不高,。7.2,。自定義輔助函數(shù)實(shí)現(xiàn)自定義輔助函數(shù)與實(shí)現(xiàn)標(biāo)量SQL函數(shù)類似。該實(shí)現(xiàn)應(yīng)該是一個(gè)類型為fts5_extension_function的C函數(shù),,定義如下:typedef struct Fts5ExtensionApi Fts5ExtensionApi; typedef struct Fts5Context Fts5Context; typedef struct Fts5PhraseIter Fts5PhraseIter; typedef void(* fts5_extension_function)(const Fts5ExtensionApi * pApi,,/ *當(dāng)前FTS版本提供的API * / Fts5Context * pFts,/ *第一個(gè)參數(shù)傳遞給pApi函數(shù)* / sqlite3_context * pCtx,,/ *返回結(jié)果/ / int nVal,,/ * apVal []數(shù)組中的值的數(shù)量* / sqlite3_value ** apVal / *結(jié)尾參數(shù)數(shù)組* /); 通過調(diào)用fts5_api對(duì)象的xCreateFunction()方法將實(shí)現(xiàn)注冊(cè)到FTS5模塊。如果已經(jīng)有一個(gè)具有相同名稱的輔助功能,,它將被新功能取代,。如果將非空xDestroy參數(shù)傳遞給xCreateFunction(),則會(huì)在數(shù)據(jù)庫(kù)句柄關(guān)閉時(shí)或者替換已注冊(cè)的輔助函數(shù)時(shí),,使用作為唯一參數(shù)傳遞的pContext指針的副本來調(diào)用它,。傳遞給輔助函數(shù)回調(diào)的最后三個(gè)參數(shù)與傳遞給標(biāo)量SQL函數(shù)的三個(gè)參數(shù)類似。除了首先傳遞給輔助函數(shù)的所有參數(shù)都可以在apVal []數(shù)組中實(shí)現(xiàn),。實(shí)現(xiàn)應(yīng)該通過內(nèi)容句柄pCtx返回結(jié)果或錯(cuò)誤,。傳遞給輔助函數(shù)回調(diào)的第一個(gè)參數(shù)是一個(gè)指向包含方法的結(jié)構(gòu)的指針,這些方法可能會(huì)被調(diào)用以獲取有關(guān)當(dāng)前查詢或行的信息,。第二個(gè)參數(shù)是一個(gè)不透明的句柄,,它應(yīng)該作為第一個(gè)參數(shù)傳遞給任何這樣的方法調(diào)用。例如,以下輔助函數(shù)定義將返回當(dāng)前行所有列中的標(biāo)記總數(shù):/ * **實(shí)現(xiàn)返回當(dāng)前行中標(biāo)記數(shù)量**的輔助函數(shù)(包括所有列),。* / static void column_size_imp(const Fts5ExtensionApi * pApi,,F(xiàn)ts5Context * pFts,sqlite3_context * pCtx,,int nVal,,sqlite3_value ** apVal){int rc; int nToken; rc = pApi-> xColumnSize(pFts,-1,,&nToken); 如果(rc == SQLITE_OK){sqlite3_result_int(pCtx,,nToken); } else {sqlite3_result_error_code(pCtx,rc); }}以下部分詳細(xì)介紹了提供給輔助功能實(shí)現(xiàn)的API,。更多的例子可以在源代碼的“fts5_aux.c”文件中找到,。7.2.1。自定義輔助函數(shù)API Referencestruct Fts5ExtensionApi {int iVersion; / *目前總是設(shè)置為3 * / void *(* xUserData)(Fts5Context *); int(* xColumnCount)(Fts5Context *); int(* xRowCount)(Fts5Context *,,sqlite3_int64 * pnRow); int(* xColumnTotalSize)(Fts5Context *,,int iCol,sqlite3_int64 * pnToken); int(* xTokenize)(Fts5Context *,,const char * pText,,int nText,/ * Text to tokenize * / void * pCtx,,/ *上下文傳遞給xToken()* / int(* xToken)(void *,,int,const char *,,int,,int,int)/ *回調(diào)* /); int(* xPhraseCount)(Fts5Context *); int(* xPhraseSize)(Fts5Context *,,int iPhrase); int(* xInstCount)(Fts5Context *,,int * pnInst); int(* xInst)(Fts5Context *,int iIdx,,int * piPhrase,,int * piCol,int * piOff); sqlite3_int64(* xRowid)(Fts5Context *); int(* xColumnText)(Fts5Context *,,int iCol,const char ** pz,,int * pn); int(* xColumnSize)(Fts5Context *,,int iCol,int * pnToken); int(* xQueryPhrase)(Fts5Context *,,int iPhrase,,void * pUserData,int(*)(const Fts5ExtensionApi *,F(xiàn)ts5Context *,,void *)); int(* xSetAuxdata)(Fts5Context *,,void * pAux,void(* xDelete)(void *)); void *(* xGetAuxdata)(Fts5Context *,,int bClear); int(* xPhraseFirst)(Fts5Context *,,int iPhrase,F(xiàn)ts5PhraseIter *,,int *,,int *); void(* xPhraseNext)(Fts5Context *,F(xiàn)ts5PhraseIter *,,int * piCol,,int * piOff); int(* xPhraseFirstColumn)(Fts5Context *,int iPhrase,,F(xiàn)ts5PhraseIter *,,int *); void(* xPhraseNextColumn)(Fts5Context *,F(xiàn)ts5PhraseIter *,,int * piCol); };void *(* xUserData)(Fts5Context *)返回?cái)U(kuò)展函數(shù)注冊(cè)的上下文指針的副本,。int(* xColumnTotalSize)(Fts5Context *,int iCol,,sqlite3_int64 * pnToken)如果參數(shù)iCol小于零,,請(qǐng)將輸出變量* pnToken設(shè)置為FTS5表中的標(biāo)記總數(shù)?;蛘?,如果iCol非負(fù)數(shù)但小于表中的列數(shù),則返回列iCol中的標(biāo)記總數(shù),,考慮FTS5表中的所有行,。如果參數(shù)iCol大于或等于表中的列數(shù),則返回SQLITE_RANGE,?;蛘撸绻l(fā)生錯(cuò)誤(例如OOM條件或IO錯(cuò)誤),,則返回適當(dāng)?shù)腟QLite錯(cuò)誤代碼,。int(* xColumnCount)(Fts5Context *)返回表中的列數(shù)。int(* xColumnSize)(Fts5Context *,,int iCol,,int * pnToken)如果參數(shù)iCol小于零,則將輸出變量* pnToken設(shè)置為當(dāng)前行中的標(biāo)記總數(shù),?;蛘撸绻鹖Col非負(fù)數(shù)但小于表中的列數(shù),請(qǐng)將* pnToken設(shè)置為當(dāng)前行的iCol列中的標(biāo)記數(shù),。如果參數(shù)iCol大于或等于表中的列數(shù),,則返回SQLITE_RANGE?;蛘?,如果發(fā)生錯(cuò)誤(例如OOM條件或IO錯(cuò)誤),則返回適當(dāng)?shù)腟QLite錯(cuò)誤代碼,。如果與使用“columnsize = 0”選項(xiàng)創(chuàng)建的FTS5表一起使用,,此函數(shù)的效率可能非常低。int(* xColumnText)(Fts5Context *,,int iCol,,const char ** pz,int * pn)此函數(shù)嘗試檢索當(dāng)前文檔的iCol列的文本,。如果成功,,則將(* pz)設(shè)置為指向包含utf-8編碼中文本的緩沖區(qū),(* pn)將設(shè)置為緩沖區(qū)的大?。ú皇亲址?,并返回SQLITE_OK。否則,,如果發(fā)生錯(cuò)誤,,則返回SQLite錯(cuò)誤代碼,并且(* pz)和(* pn)的最終值未定義,。int(* xPhraseCount)(Fts5Context *)返回當(dāng)前查詢表達(dá)式中的短語(yǔ)數(shù)量,。int(* xPhraseSize)(Fts5Context *,int iPhrase)返回查詢短語(yǔ)iPhrase中的標(biāo)記數(shù),。短語(yǔ)從零開始編號(hào),。int(* xInstCount)(Fts5Context *,int * pnInst)將* pnInst設(shè)置為當(dāng)前行內(nèi)查詢內(nèi)所有短語(yǔ)出現(xiàn)的總次數(shù),。如果成功則返回SQLITE_OK,,如果發(fā)生錯(cuò)誤則返回錯(cuò)誤代碼(即SQLITE_NOMEM)。如果與使用“detail = none”或“detail = column”選項(xiàng)創(chuàng)建的FTS5表一起使用,,此API可能會(huì)很慢,。如果FTS5表是使用“detail = none”或“detail = column”和“content =”選項(xiàng)(即它是無內(nèi)容表)創(chuàng)建的,則此API始終返回0. int(* xInst)(Fts5Context * ,,int iIdx,,int * piPhrase,int * piCol,,int * piOff)查詢當(dāng)前行中詞組匹配iIdx的詳細(xì)信息。短語(yǔ)匹配從零開始編號(hào),因此iIdx參數(shù)應(yīng)該大于或等于零并小于xInstCount()輸出的值,。通常,,輸出參數(shù)* piPhrase設(shè)置為短語(yǔ)編號(hào),* piCol設(shè)置為其出現(xiàn)的列,,* piOff設(shè)置短語(yǔ)的第一個(gè)標(biāo)記的標(biāo)記位移,。例外情況是如果該表是使用指定的偏移量= 0選項(xiàng)創(chuàng)建的。在這種情況下* piOff始終設(shè)置為-1,。如果成功,,則返回SQLITE_OK;如果發(fā)生錯(cuò)誤,則返回錯(cuò)誤代碼(即SQLITE_NOMEM),。如果與使用“detail = none”或“detail = column”選項(xiàng)創(chuàng)建的FTS5表一起使用,,此API可能會(huì)很慢。sqlite3_int64(* xRowid)(Fts5Context *)返回當(dāng)前行的rowid,。int(* xTokenize)(Fts5Context *,,const char * pText,int nText,,void * pCtx,,int(* xToken)(void *,int,,const char *,,int,int,,int)使用屬于FTS5表,。int(* xQueryPhrase)(Fts5Context *,int iPhrase,,void * pUserData,,int(*)(const Fts5ExtensionApi *,F(xiàn)ts5Context *,,void *))此API函數(shù)用于查詢當(dāng)前查詢的短語(yǔ)iPhrase的FTS表,。具體而言,查詢等同于:... FROM ftstable WHERE ftstable MATCH $ p ORDER BY rowid with $ p設(shè)置為與當(dāng)前查詢的短語(yǔ)iPhrase相當(dāng)?shù)亩陶Z(yǔ)執(zhí)行,。任何適用于當(dāng)前查詢的短語(yǔ)iPhrase的列過濾器都包含在$ p中,。對(duì)于訪問的每一行,都會(huì)調(diào)用作為第四個(gè)參數(shù)傳遞的回調(diào)函數(shù),。傳遞給回調(diào)函數(shù)的上下文和API對(duì)象可用于訪問每個(gè)匹配行的屬性,。調(diào)用Api.xUserData()返回作為第三個(gè)參數(shù)傳遞給pUserData的指針的副本。如果回調(diào)函數(shù)返回除SQLITE_OK以外的任何值,,則會(huì)放棄查詢并立即返回xQueryPhrase函數(shù),。如果返回的值是SQLITE_DONE,,xQueryPhrase返回SQLITE_OK。否則,,錯(cuò)誤代碼向上傳播,。如果查詢順利完成,則返回SQLITE_OK,?;蛘撸绻诓樵兺瓿芍鞍l(fā)生了某些錯(cuò)誤或者被回調(diào)中止,,則會(huì)返回SQLite錯(cuò)誤代碼,。int(* xSetAuxdata)(Fts5Context *,void * pAux,,void(* xDelete)(void *))將作為第二個(gè)參數(shù)傳遞的指針保存為擴(kuò)展函數(shù)“輔助數(shù)據(jù)”,。然后可以通過使用xGetAuxdata()API作為相同MATCH查詢的一部分創(chuàng)建的相同fts5擴(kuò)展函數(shù)的當(dāng)前或未來任何調(diào)用來檢索指針。每個(gè)擴(kuò)展功能為每個(gè)FTS查詢(MATCH表達(dá)式)分配一個(gè)輔助數(shù)據(jù)槽,。如果為單個(gè)FTS查詢多次調(diào)用擴(kuò)展函數(shù),,則所有調(diào)用共享一個(gè)輔助數(shù)據(jù)上下文。如果在調(diào)用該函數(shù)時(shí)已經(jīng)有一個(gè)輔助數(shù)據(jù)指針,,那么它將被新指針取代,。如果xDelete回調(diào)與原始指針一起指定,則在此時(shí)調(diào)用它,。如果指定了xDelete回調(diào),,也在FTS5查詢完成后在輔助數(shù)據(jù)指針上調(diào)用。如果在此函數(shù)中發(fā)生錯(cuò)誤(例如OOM條件),,則輔助數(shù)據(jù)將設(shè)置為NULL并返回錯(cuò)誤代碼,。如果xDelete參數(shù)不是NULL,則在返回之前在輔助數(shù)據(jù)指針上調(diào)用它,。void *(* xGetAuxdata)(Fts5Context *,,int bClear)返回fts5擴(kuò)展函數(shù)的當(dāng)前輔助數(shù)據(jù)指針。有關(guān)詳細(xì)信息,,請(qǐng)參閱xSetAuxdata()方法,。如果bClear參數(shù)非零,那么在此函數(shù)返回之前,,輔助數(shù)據(jù)將被清除(設(shè)置為NULL),。在這種情況下,xDelete,,如果有的話,,不會(huì)被調(diào)用。int(* xRowCount)(Fts5Context *,,sqlite3_int64 * pnRow)此函數(shù)用于檢索表中的總行數(shù),。換句話說,,將返回相同的值:SELECT count(*)FROM ftstable; int(* xPhraseFirst)(Fts5Context *,int iPhrase,,F(xiàn)ts5PhraseIter *,,int *,int *)使用此函數(shù)以及類型Fts5PhraseIter和xPhraseNext方法來遍歷當(dāng)前行中單個(gè)查詢短語(yǔ)的所有實(shí)例,。這與通過xInstCount / xInst API可訪問的信息相同。雖然xInstCount / xInst API更便于使用,,但在某些情況下,,此API可能會(huì)更快。要遍歷短語(yǔ)iPhrase的實(shí)例,,請(qǐng)使用以下代碼:Fts5PhraseIter iter; int iCol,,iOff; 對(duì)于(pApi-> xPhraseFirst(pFts,iPhrase,,&iter,,&iCol,&iOff); iCol> = 0; pApi-> xPhraseNext(pFts,,&iter,,&iCol,&iOff)){//在列偏移量iOff處的短語(yǔ)iPhrase實(shí)例iCol}上面定義了Fts5PhraseIter結(jié)構(gòu),。應(yīng)用程序不應(yīng)該直接修改此結(jié)構(gòu) - 只應(yīng)按照以下所示使用xPhraseFirst()和xPhraseNext()API方法(以及xPhraseFirstColumn()和xPhraseNextColumn())如上所示,。如果與使用“detail = none”或“detail = column”選項(xiàng)創(chuàng)建的FTS5表一起使用,此API可能會(huì)很慢,。如果FTS5表是用“detail = none”或“detail = column”和“content =”選項(xiàng)創(chuàng)建的(即如果它是無內(nèi)容表),,那么這個(gè)API總是遍歷一個(gè)空集(所有調(diào)用xPhraseFirst )將iCol設(shè)置為-1)。void(* xPhraseNext)(Fts5Context *,,F(xiàn)ts5PhraseIter *,,int * piCol,int * piOff)請(qǐng)參見上面的xPhraseFirst,。int(* xPhraseFirstColumn)(Fts5Context *,,int iPhrase,F(xiàn)ts5PhraseIter *,,int *)這個(gè)函數(shù)和xPhraseNextColumn()類似于上面描述的xPhraseFirst()和xPhraseNext()API,。不同之處在于,不是遍歷當(dāng)前行中所有短語(yǔ)的實(shí)例,,而是使用這些API遍歷當(dāng)前行中包含指定短語(yǔ)的一個(gè)或多個(gè)實(shí)例的一組列,。例如:Fts5PhraseIter iter; int iCol; 對(duì)于(pApi-> xPhraseFirstColumn(pFts,iPhrase,,&iter,,&iCol); iCol> = 0; pApi-> xPhraseNextColumn(pFts,,&iter,&iCol)){//列iCol包含至少一個(gè)短語(yǔ)iPhrase實(shí)例}如果與使用“detail = none”選項(xiàng)創(chuàng)建的FTS5表一起使用,,則速度會(huì)很慢,。如果FTS5表是用“detail = none”“content =”選項(xiàng)創(chuàng)建的(即如果它是無內(nèi)容表),那么這個(gè)API總是遍歷一個(gè)空集(所有對(duì)xPhraseFirstColumn()的調(diào)用都將iCol設(shè)置為-1),。使用此API及其伴侶xPhraseFirstColumn()訪問的信息也可以使用xPhraseFirst / xPhraseNext(或xInst / xInstCount)獲取,。這個(gè)API的主要優(yōu)點(diǎn)是,與“detail = column”表一起使用時(shí),,它的效率明顯高于這些替代方法,。void(* xPhraseNextColumn)(Fts5Context *,,F(xiàn)ts5PhraseIter *,,int * piCol)請(qǐng)參閱上面的xPhraseFirstColumn。8. fts5vocab虛擬表模塊fts5vocab虛擬表模塊允許用戶直接從FTS5全文索引中提取信息,。fts5vocab模塊是FTS5的一部分 - 只要FTS5是可用的,。每個(gè)fts5vocab表都與一個(gè)FTS5表相關(guān)聯(lián)。通常通過在CREATE VIRTUAL TABLE語(yǔ)句中指定兩個(gè)參數(shù)來替代列名創(chuàng)建fts5vocab表 - 關(guān)聯(lián)的FTS5表的名稱和fts5vocab表的類型,。目前有三種類型的fts5vocab表格; “row”,,“col”和“instance”。除非在“temp”數(shù)據(jù)庫(kù)??中創(chuàng)建了fts5vocab表,,否則它必須是與關(guān)聯(lián)的FTS5表相同數(shù)據(jù)庫(kù)的一部分,。 - 創(chuàng)建一個(gè)fts5vocab“行” 表來查詢屬于FTS5表“ft1”的全文索引。CREATE VIRTUAL TABLE ft1_v USING fts5vocab('ft1',,'row'); - 創(chuàng)建一個(gè)fts5vocab“col”表來查詢屬于FTS5表“ft2”的全文索引,。CREATE VIRTUAL TABLE ft2_v USING fts5vocab(ft2,col); - 創(chuàng)建一個(gè)fts5vocab“實(shí)例”表來查詢?nèi)乃饕?- 屬于FTS5表“ft3”,。CREATE VIRTUAL TABLE ft3_v USING fts5vocab(ft3,,instance); 如果在臨時(shí)數(shù)據(jù)庫(kù)中創(chuàng)建了fts5vocab表,則它可能與任何附加數(shù)據(jù)庫(kù)中的FTS5表相關(guān)聯(lián),。為了將fts5vocab表附加到位于非temp的數(shù)據(jù)庫(kù)中的FTS5表,,數(shù)據(jù)庫(kù)的名稱將插入CREATE VIRTUAL TABLE參數(shù)中的FTS5表名之前。例如: - 創(chuàng)建一個(gè)fts5vocab“行”表來查詢屬于數(shù)據(jù)庫(kù)“main”中的FTS5表“ft1”的全文索引,。CREATE VIRTUAL TABLE temp.ft1_v USING fts5vocab(main,,'ft1','row'); - 創(chuàng)建一個(gè)fts5vocab“col”表來查詢屬于附屬數(shù)據(jù)庫(kù)“aux”中的FTS5表“ft2”的全文索引,。CREATE VIRTUAL TABLE temp.ft2_v USING fts5vocab('aux',,ft2,col); - 創(chuàng)建一個(gè)fts5vocab“實(shí)例”表來查詢?nèi)乃饕?- 屬于附加數(shù)據(jù)庫(kù)“other”中的FTS5表“ft3”,。CREATE VIRTUAL TABLE temp.ft2_v USING fts5vocab('aux',,ft3,,'instance'); 在除“temp”之外的任何數(shù)據(jù)庫(kù)中創(chuàng)建fts5vocab表時(shí),指定三個(gè)參數(shù)會(huì)導(dǎo)致錯(cuò)誤,。類型“行”的fts5vocab表包含關(guān)聯(lián)的FTS5表中每個(gè)不同術(shù)語(yǔ)的一行,。表格列如下所示:ColumnContentsterm存儲(chǔ)在FTS5 index中的術(shù)語(yǔ).doc至少包含一個(gè)term.cnt實(shí)例的行數(shù)。該術(shù)語(yǔ)在整個(gè)FTS5表中的總實(shí)例數(shù),。類型為“col”的fts5vocab表包含關(guān)聯(lián)的FTS5表中每個(gè)不同的術(shù)語(yǔ)/列組合的一行,。表格列如下所示:ColumnContentsterm存儲(chǔ)在FTS5 index.col中的術(shù)語(yǔ)包含term的FTS5表格列的名稱.docFTS5表中列數(shù)為$ col的列至少包含一個(gè)術(shù)語(yǔ)實(shí)例的行數(shù)。 cnt在FTS5表的列$ col中出現(xiàn)的術(shù)語(yǔ)實(shí)例的總數(shù)(考慮所有行),。類型為“instance”的fts5vocab表包含存儲(chǔ)在關(guān)聯(lián)的FTS索引中的每個(gè)詞條實(shí)例的一行,。假設(shè)FTS5表格的'detail'選項(xiàng)設(shè)置為'full',表格列如下所示:ColumnContentsterm該術(shù)語(yǔ),,存儲(chǔ)在FTS5索引中..doc包含術(shù)語(yǔ)instance.col的文檔的rowid列名稱其中包含術(shù)語(yǔ)instance.offset其列中的術(shù)語(yǔ)實(shí)例的索引。術(shù)語(yǔ)按從0開始的順序進(jìn)行編號(hào),。如果FTS5表格的'detail'選項(xiàng)設(shè)置為'col',,則創(chuàng)建 ColumnContentsterm存儲(chǔ)在FTS5索引中的術(shù)語(yǔ).doc包含術(shù)語(yǔ)instance.col的文檔的rowid包含術(shù)語(yǔ)instance.offset的列的名稱其列中的術(shù)語(yǔ)實(shí)例索引。術(shù)語(yǔ)按從0開始的順序進(jìn)行編號(hào),。如果FTS5表格的'detail'選項(xiàng)設(shè)置為'col',,則創(chuàng)建 ColumnContentsterm存儲(chǔ)在FTS5索引中的術(shù)語(yǔ).doc包含術(shù)語(yǔ)instance.col的文檔的rowid包含術(shù)語(yǔ)instance.offset的列的名稱其列中的術(shù)語(yǔ)實(shí)例索引。術(shù)語(yǔ)按從0開始的順序進(jìn)行編號(hào),。如果FTS5表格的'detail'選項(xiàng)設(shè)置為'col',,則創(chuàng)建實(shí)例虛擬表的偏移列始終包含NULL,。在這種情況下,,每個(gè)唯一的term / doc / col組合在表格中有一行?;蛘?,如果FTS5表的'detail'設(shè)置為'none',,那么offsetcol都是創(chuàng)建的始終包含NULL值。對(duì)于detail = none FTS5表,,每個(gè)唯一的term / doc組合在fts5vocab表中有一行,。示例: - 假定使用以下命令創(chuàng)建數(shù)據(jù)庫(kù):CREATE VIRTUAL TABLE ft1 USING fts5(c1,c2); INSERT INTO ft1 VALUES('apple banana cherry',,'banana banana cherry'); INSERT INTO ft1 VALUES('櫻桃櫻桃',,'約會(huì)日期'); - 然后查詢下面的fts5vocab表(鍵入“col”)返回: - - apple | c1 | 1 | 1 - 香蕉| c1 | 1 | 1 - 香蕉| c2 | 1 | 2 - 櫻桃| c1 | 2 | 4 - 櫻桃| c2 | 1 | 1 - 日期| c3 | 1 | 3 - 創(chuàng)建虛擬表格ft1_v_col使用fts5vocab(ft1,col); - 查詢類型為“row”的fts5vocab表返回: - - 蘋果| 1 | 1 - 香蕉| 1 | 3 - 櫻桃| 2 | 5 - 日期| 1 | 3 - CREATE VIRTUAL TABLE ft1_v_row使用fts5vocab(ft1,,row); - 對(duì)于類型“實(shí)例”INSERT INTO ft1 VALUES('apple banana cherry',,'banana banana cherry'); INSERT INTO ft1 VALUES('櫻桃櫻桃','約會(huì)日期'); - - 蘋果| 1 | c1 | 0 - 香蕉| 1 | c1 | 1 - 香蕉| 1 | c2 | 0 - 香蕉| 1 | c2 | 1 - 櫻桃| 1 | c1 | 2 - 櫻桃| 1 | c2 | 2 - 櫻桃| 2 | c1 | 0 - 櫻桃| 2 | c1 | 1 - 櫻桃| 2 | c1 | 2 - 日期| 2 | c2 | 0 - 日期| 2 | c2 | 1 - 日期| 2 | c2 | 2 - CREATE VIRTUAL TABLE ft1_v_instance USING fts5vocab(ft1,,instance);附錄A:與FTS3 / 4比較也可以使用類似但更成熟的FTS3 / 4模塊,。FTS5是FTS4的新版本,,包含各種修補(bǔ)程序和問題解決方案,在不犧牲向后兼容性的情況下無法在FTS4中修復(fù),。下面介紹其中的一些問題,。應(yīng)用程序移植指南為了使用FTS5而不是FTS3或FTS4,應(yīng)用程序通常只需要很少的修改,。其中大部分分為三類 - 用于創(chuàng)建FTS表的CREATE VIRTUAL TABLE語(yǔ)句所需的更改,,用于對(duì)表執(zhí)行查詢的SELECT查詢所需的更改以及使用FTS輔助功能的應(yīng)用程序所需的更改。對(duì)CREATE VIRTUAL TABLE語(yǔ)句的更改 應(yīng)用程序移植指南為了使用FTS5而不是FTS3或FTS4,,應(yīng)用程序通常只需要很少的修改,。其中大部分分為三類 - 用于創(chuàng)建FTS表的CREATE VIRTUAL TABLE語(yǔ)句所需的更改,用于對(duì)表執(zhí)行查詢的SELECT查詢所需的更改以及使用FTS輔助功能的應(yīng)用程序所需的更改,。對(duì)CREATE VIRTUAL TABLE語(yǔ)句的更改 應(yīng)用程序移植指南為了使用FTS5而不是FTS3或FTS4,,應(yīng)用程序通常只需要很少的修改。其中大部分分為三類 - 用于創(chuàng)建FTS表的CREATE VIRTUAL TABLE語(yǔ)句所需的更改,,用于對(duì)表執(zhí)行查詢的SELECT查詢所需的更改以及使用FTS輔助功能的應(yīng)用程序所需的更改,。對(duì)CREATE VIRTUAL TABLE語(yǔ)句的更改
  1. 模塊名稱必須從“fts3”或“fts4”更改為“fts5”。
  1. 必須從列定義中刪除所有類型信息或約束規(guī)范,。FTS3 / 4忽略列定義中列名后面的所有內(nèi)容,,F(xiàn)TS5嘗試解析它(并且如果失敗則報(bào)告錯(cuò)誤)。
  1. “matchinfo = fts3”選項(xiàng)不可用,?!癱olumnsize = 0”選項(xiàng)是等效的。
  1. notindexed =選項(xiàng)不可用,。將UNINDEXED添加到列定義中是等效的,。
  1. ICU標(biāo)記器不可用。
  1. The compress=, uncompress= and languageid= options are not available. There is as of yet no equivalent for their functionality. -- FTS3/4 statement CREATE VIRTUAL TABLE t1 USING fts4( linkid INTEGER, header CHAR(20), text VARCHAR, notindexed=linkid, matchinfo=fts3, tokenizer=unicode61 ); -- FTS5 equivalent (note - the "tokenizer=unicode61" option is not -- required as this is the default for FTS5 anyway) CREATE VIRTUAL TABLE t1 USING fts5( linkid UNINDEXED, header, text, columnsize=0 );Changes to SELECT statements
  1. “docid”別名不存在,。應(yīng)用程序必須使用“rowid”,。
  1. 將列過濾器既指定為FTS查詢的一部分,又將列用作MATCH操作符的LHS時(shí)的查詢行為稍有不同,。對(duì)于列“a”和“b”以及類似于以下查詢的表格:... MATCH'b:字符串'FTS3 / 4在列“b”中搜索匹配項(xiàng),。但是,F(xiàn)TS5總是返回零行,,因?yàn)槭紫葘?duì)列“b”進(jìn)行篩選,,然后對(duì)列“a”進(jìn)行篩選,而不留下任何結(jié)果,。換句話說,,在FTS3 / 4中,內(nèi)部過濾器覆蓋外部,在FTS5中,,兩個(gè)過濾器都被應(yīng)用,。
  1. FTS查詢語(yǔ)法(MATCH運(yùn)算符的右側(cè))在某些方面發(fā)生了變化。FTS5語(yǔ)法非常接近FTS4“增強(qiáng)語(yǔ)法”,。主要區(qū)別在于FTS5對(duì)查詢字符串中無法識(shí)別的標(biāo)點(diǎn)符號(hào)和類似內(nèi)容感到煩惱,。與FTS3 / 4一起工作的大多數(shù)查詢也應(yīng)該與FTS5一起使用,而那些不應(yīng)該返回解析錯(cuò)誤的查詢也適用于FTS5,。

輔助功能更改

FTS5沒有matchinfo()或offset()函數(shù),,并且snippet()函數(shù)的功能不如FTS3 / 4中的全功能。但是,,由于FTS5確實(shí)提供了允許應(yīng)用程序創(chuàng)建自定義輔助功能的API,,因此可以在應(yīng)用程序代碼中實(shí)施任何必需的功能。

FTS5提供的一組內(nèi)置輔助功能可能在未來得到改進(jìn),。

其他事宜

  1. fts4aux模塊提供的功能現(xiàn)在由fts5vocab提供,。這兩個(gè)表的模式略有不同。

2. FTS3 / 4“merge = X,,Y”命令已被FTS5合并命令取代,。

3. FTS3 / 4“automerge = X”命令已由FTS5 automerge選項(xiàng)取代。

技術(shù)差異總結(jié)

FTS5與FTS3 / 4的相似之處在于每一個(gè)的主要任務(wù)是維護(hù)從一組文檔中的每個(gè)唯一標(biāo)記到該標(biāo)記的實(shí)例列表的映射,,其中每個(gè)實(shí)例由其出現(xiàn)的文檔標(biāo)識(shí)及其在該文件中的位置。例如:

-- Given the following SQL:
CREATE VIRTUAL TABLE ft USING fts5(a, b);
INSERT INTO ft(rowid, a, b) VALUES(1, 'X Y', 'Y Z');
INSERT INTO ft(rowid, a, b) VALUES(2, 'A Z', 'Y Y');

-- The FTS5 module creates the following mapping on disk:
A --> (2, 0, 0)
X --> (1, 0, 0)
Y --> (1, 0, 1) (1, 1, 0) (2, 1, 0) (2, 1, 1)
Z --> (1, 1, 1) (2, 0, 1)

在上面的例子中,,每個(gè)三元組通過rowid,,列編號(hào)(列從0開始按順序從左到右編號(hào))和位置在列值中的位置(列值中的第一個(gè)標(biāo)記為0,第二個(gè)是1,,依此類推),。使用此索引,F(xiàn)TS5能夠及時(shí)為諸如“包含標(biāo)記”A“的所有文檔的集合”或“包含序列'Y Z'的所有文檔的集合”提供及時(shí)答案,。與單個(gè)令牌關(guān)聯(lián)的實(shí)例列表稱為“實(shí)例列表”,。

FTS3 / 4和FTS5之間的主要區(qū)別在于,在FTS3 / 4中,,每個(gè)實(shí)例列表存儲(chǔ)為單個(gè)大型數(shù)據(jù)庫(kù)記錄,,而在FTS5中,大型實(shí)例列表在多個(gè)數(shù)據(jù)庫(kù)記錄之間分配,。這對(duì)于處理包含大型列表的大型數(shù)據(jù)庫(kù)具有以下含義:

  • FTS5能夠?qū)?shí)例列表逐步加載到內(nèi)存中,,以減少內(nèi)存使用量和峰值分配大小。FTS3 / 4經(jīng)常將整個(gè)實(shí)例列表加載到內(nèi)存中,。
  • 處理具有多個(gè)標(biāo)記的查詢時(shí),,F(xiàn)TS5有時(shí)可以通過檢查大型實(shí)例列表的子集來確定查詢是否可以得到應(yīng)答。FTS3 / 4幾乎總是需要遍歷整個(gè)實(shí)例列表。
  • 如果實(shí)例列表增長(zhǎng)得如此之大以至于超過了SQLITE_MAX_LENGTH限制,,F(xiàn)TS3 / 4將無法處理它,。FTS5沒有這個(gè)問題。由于這些原因,,許多復(fù)雜的查詢可能會(huì)使用更少的內(nèi)存并使用FTS5運(yùn)行得更快,。FTS5與FTS3 / 4的其他不同之處在于:
  • FTS5支持“ORDER BY排名”,按照相關(guān)性遞減的順序返回結(jié)果,。
  • FTS5具有一個(gè)API,,允許用戶為高級(jí)排名和文本處理應(yīng)用程序創(chuàng)建自定義輔助功能。特殊的“等級(jí)”列可以映射到一個(gè)自定義的輔助函數(shù),,這樣在查詢中添加“ORDER BY等級(jí)”就可以按預(yù)期工作,。
  • FTS5默認(rèn)識(shí)別unicode分隔符和大小寫等價(jià)。這也可以使用FTS3 / 4,,但必須明確啟用,。
  • 查詢語(yǔ)法已在必要時(shí)進(jìn)行了修改,以消除歧義,,并使查詢條件中的特殊字符變得可能,。
  • 默認(rèn)情況下,F(xiàn)TS3 / 4偶爾會(huì)在用戶執(zhí)行的INSERT,,UPDATE或DELETE語(yǔ)句中將兩個(gè)或更多構(gòu)成其全文索引的b-樹合并在一起,。這意味著在FTS3 / 4表上的任何操作可能會(huì)變得非常慢,因?yàn)镕TS3 / 4可能無法預(yù)料地選擇將兩個(gè)或更多的大型b-樹合并在一起,。FTS5默認(rèn)使用增量合并,,這限制了在任何給定的INSERT,UPDATE或DELETE操作中可能發(fā)生的處理量,。
 SQLite is in the Public Domain.

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多