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,,用戶使用一列或多列創(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í)行全文查詢:
如果使用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)容的行:
通過提供更復(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ò)展,。
$ 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),,它們都做同樣的事情:
另一個(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á)式中,,可以用以下兩種方式之一來指定字符串:
- 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組將匹配文檔:
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)先順序,操作是:
括號(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):
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é)中有介紹:
也可以為FTS5創(chuàng)建自定義標(biāo)記,。這里描述了這樣做的API。 4.3.1.Unicode61 Tokenizerunicode標(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):
例如: -- 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 TokenizerAscii標(biāo)記器與Unicode61標(biāo)記器類似,不同之處在于:
例如: -- 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):
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)容:
如果detail選項(xiàng)設(shè)置為none,,那么對(duì)于每個(gè)術(shù)語(yǔ),,F(xiàn)TS索引只記錄rowid。列和偏移量信息都被省略,。除了上面針對(duì)detail = column模式列出的限制外,,這還會(huì)帶來以下額外限制:
在一個(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)置的輔助功能:
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ù)量,。k1和b都是常數(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()。解釋如下:
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ù):
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)行合并:
通過在命令執(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è):
其中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ò)展:
本文檔中描述的內(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è)值之一:
對(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è)問題:
標(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ǔ),。
輔助功能更改FTS5沒有matchinfo()或offset()函數(shù),,并且snippet()函數(shù)的功能不如FTS3 / 4中的全功能。但是,,由于FTS5確實(shí)提供了允許應(yīng)用程序創(chuàng)建自定義輔助功能的API,,因此可以在應(yīng)用程序代碼中實(shí)施任何必需的功能。 FTS5提供的一組內(nèi)置輔助功能可能在未來得到改進(jìn),。 其他事宜
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ù)具有以下含義:
SQLite is in the Public Domain. |
|