並非所有的數據庫引擎都支持全文本搜索
MySQL 支持幾種基本的數據庫引擎,最常用的兩種是MyISAM 和 InnoDB,MyISAM 支持全文本搜索,而InnoDB 不支持
所以要使用全文本搜索的時候要注意,你的表引用的是不是MyISAM
之前了解過兩個like 和 regxp
like關鍵字利用通配符匹配文本(或部分文本),可以查找包含特殊值或部分值的行(不管這些值位於列內的什么位置)
regxp 可以編寫查找所需行的非常復雜的匹配模式。
那他們有哪些限制來
1、通配符和正則表達式匹配,通常要求MySQL 嘗試匹配表中所有行,而這些搜索極少使用到表索引。因此,由於被搜索行數不斷增加,這些搜索可能非常耗時。
2、使用通配符和正則表達式匹配很難明確的控制匹配什么和不匹配什么,
3、基於通配符和正則雖然可以提供非常靈活的搜索,但他們都不能提供一種智能化的選擇結果的方法。
因此,推出了本文重點全文本搜索,可以解決以上以及更多的限制
使用全文本搜索,MySQL不需要分別查看每個行,不需要分別分析和處理每個詞,MySQL創建指定列中各詞的一個索引,可以針對這些詞搜索,快速有效的決定哪些詞匹配(哪些行包括他們),哪些詞不匹配,以及他們的匹配頻率等等。
簡單使用
注意:
1、為了進行全文本搜索,必須索引被搜索的列,而且要隨着數據的改變不斷的重新索引。但是在對表列進行適當設計后,MySQL自動進行所有的索引和重新索引。
2、在索引后 select可以與 match() 和Against() 一起使用以實際執行搜索。
3、一般在創建表的時候啟用全文本搜索,在創建表的時候增加 FULLTEXT(列名),並指定使用的引擎 ENGINE=MyISAM;
如下:
上述:mysql 根據 子句 fulltesxt(note_text) 的指示對列名note_text 進行索引,
注意
1、fulltesxt 既可以指定單列也可以指定多列,
2、定義后MySQL會自動維護該索引,在增加、更新或刪除行時,索引隨之更新。
3、可以在創建表時指定fulltest, 也可以稍后指定,不過,所有已有數據必須立即索引
4、不要在導入數據時使用索引,建議先導數據在修改表啟動索引,這樣有助於更快的導入數據(這樣使索引數據的總時間小於在導入每行時分別進行索引所需要的總時間)。
進行全文本搜索的兩個函數
match() : 指定被搜索的列,
against() : 指定要使用的搜索表達式
-- 檢索單個列 note_text ,將字段note_text中含有rabbit的行檢索出來
select note_text from productnotes where match(note_text) against('rabbit');
select 語句檢索單個列onte_text 由於where 子句,一個全文本搜索被執行,match(note_text) 指示mysql 針對列名為note_text 的進行搜索,against('rabbit') 指定在該列中搜索文本中含有 rabbit 的行,包含的行就返回
注意:
1、傳遞給match() 的值必須與fulltext() 定義中的相同,如果指定多個列,則必須列出他們,而且次序也要相同
2、全文本搜索不區分大小寫,除非使用 binary 方式
使用 like 和 regexp 的方式實現
select note_text from productnotes where note_text like '%rabbit%'; select note_text from productnotes where note_text regexp 'rabbit';
發現這兩種方式檢索出來的兩行,與使用全文本搜索檢索出來的 順序(次序)不同,而且都沒有使用order by
為啥來
因為使用全文本搜索返回的數據,以文本匹配的良好程度排序匹配,雖然兩行都有rabbit 這個詞,但是一個位置在第3個詞,另一個位置在第20個詞,所以全文本搜索根據具有高等級的行先返回(這也可能是真正想要的)。而like 沒有指定也不會以特別有用的順序返回數據。
如何計算他們的程度的來
select note_text,match(note_text) against('rabbit') as rank from productnotes;
match () 和 against() 用來建立一個計算列(別名rank),將此列包含全文本搜索計算出等級值
等級計算方式:mysql 根據行中詞的數目、唯一詞的數目、整個索引中詞的總數以及包含該詞的行的數目計算出來。其中不含有的為 0 ,包含的都有一個等級值,等級值越高檢索出來后的排列越靠前。如果指定多個搜索項,則包含多數匹配詞的那些行將比包含較少詞(或僅有一個匹配)的那些行等級高。
全文本搜索提供了like 不具有的功能,而且由於數據是索引的,全文本搜索還較快
2、查詢擴展(WITH QUERY EXPANSION):用來設法放寬所返回的全文本搜索結果的范圍。
就是首先將根據關鍵詞全文本搜索找出來行,然后再根據返回出來的行,從中選擇有用的詞,在和關鍵詞一塊作為查詢條件進行搜索。
查詢擴展只適用於mysql 4.1.1 或更高級的版本
使用查詢擴展時,mysql 對數據和索引進行兩遍掃描來完成搜索,找出可能相關的結果,即使他們並不精確的包含所查找的詞。
1、首先,進行一個基本的全文本搜索,找出與搜索條件匹配的所有行
2、然后,mysql 檢查這些匹配行並選擇所有有用的詞(根據關鍵詞檢索出來的那個行從中選擇有用的詞)
3、最后,MySQL再次進行全文本搜索,這次不僅使用原來的條件,還要使用所有有用的詞
-- 啟用查詢擴展 WITH QUERY EXPANSION select note_text from productnotes where match(note_text) against('anvils' WITH QUERY EXPANSION);
從上述可以看出,第一行有 anvils (鐵砧),剩下的6行都沒有,第二行根據 第一行中的兩個有特點的詞(customer(顧客)和 Recommend(推薦)),在進行查找,為啥選customer作為檢索的詞可能是在此行中出現的較多,還是個主語,了解就行
使用查詢擴展檢索出來的行更多,表中的行越多使用查詢擴展返回的結果越好 ,因為更多的選擇意味着更有機會把你快要忘記的那個找到。
3、布爾文本搜索(IN BOOLEAN MODE)
MySQL支持全文本搜索的另一種形式,布爾方式(boolean mode)
注意:
1、布爾方式即使沒有定義fulltext 索引,也可以使用,但是它是一種非常緩慢的操作(其性能將隨着數據i量的增加而降低)
2、要匹配的詞
3、要排斥的詞(如果某行包含這個詞,則不返回,即使它包含其他指定的詞)
4、排列提示(指定某些詞比其他詞更重要,更重要的詞等級更高)
5、表達式分組
6、另外一些內容
-- 簡單使用 select note_text from productnotes where match(note_text) against ('heavy' in boolean mode);
另一種用法,指定排斥的詞
-- 匹配包含 但不包含 任意以rope 開始的詞的行 select note_text from productnotes where match(note_text) against ('heavy -rope*' in boolean mode);
如果數據的的版本是 mysql 4.x 上面可能不反回任何行,其不支持 * ,要改為 -ropes 意思變成 並排除含有 ropes 的行
上述的 - 和 * 就是全文本布爾操作符
小小使用
注意:在布爾方式中不按照等級值降序排列返回行
全文本搜索的使用說明
1、在索引全文本數據時,短詞被忽略且從索引中排除。短詞定義為那些具有3個或3個以下字符的詞(如果需要,這個數目可以改)
2、MySQL帶有一個內建的非用詞(stopword)列表,這些詞在索引全文本數據時總是被忽略。如果需要,可以覆蓋這個列表
3、許多詞出現的頻率很高,搜索他們沒有用處(返回太多的結果),因此,MySQL規定了一條50%規則,如果一個詞出現50%以上的行中。則將他作為一個非用詞忽略。50%規則不用於 IN BOOLEAN MODE
4、如果表中的行數少於3行,則全文本搜索不返回結果(因為每個詞或者不出現,或者至少出現在50%行中)
5、忽略詞中的單引號,列如: don‘t 索引為dont
6、不具有詞分隔符(包括日語和漢語)的語言不能恰當地返回全文本搜索結果
7、僅在myisam 數據引擎中支持全文本搜索
8、鄰近搜索是許多全文本搜索支持的一個特定,它能搜索相鄰的詞(在相同的句子中,相同段落中或者在特定數目的詞的部分中等等),但是MySQL全文本搜索現在不支持鄰近操作符
9、MySQL使用 match() 和 against() 函數進行全文本搜索
10、查詢擴展(WITH QUERY EXPANSION)
11、布爾文本搜索(IN BOOLEAN MODE)