語法:
MATCH (col1,col2,...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION])
。 MySQL中的全文索引類型FULLTEXT的索引。 FULLTEXT 索引只可用於 MyISAM表;他們可以從CHAR、 VARCHAR或TEXT欄位中作為CREATE TABLE語句的一部分建立,或是隨後使用ALTER TABLE 或 CREATE INDEX被加入。對於較大的資料集,將你的資料輸入一個沒有FULLTEXT索引的表中,然後建立索引, 其速度比把資料輸入現有FULLTEXT索引的速度更為快。
全文搜尋同MATCH()函數一起執行。
mysql> CREATE TABLE articles ( -> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, -> title VARCHAR(200), -> body TEXT, -> FULLTEXT (title,body) -> );Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO articles (title,body) VALUES -> ('MySQL Tutorial','DBMS stands for DataBase ...'), -> ('How To Use MySQL Well','After you went through a ...'), -> ('Optimizing MySQL','In this tutorial we will show ...'), -> ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), -> ('MySQL vs. YourSQL','In the following database comparison ...'), -> ('MySQL Security','When configured properly, MySQL ...');Query OK, 6 rows affected (0.00 sec) Records: 6 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM articles -> WHERE MATCH (title,body) AGAINST ('database'); +----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 1 | MySQL Tutorial | DBMS stands for DataBase ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec)
MATCH()函數對於一個字串執行資料庫內的自然語言搜尋。一個資料庫就是1套1個或2個包含在FULLTEXT內的欄位。搜尋字串作為對AGAINST()的參數而被給定。對於表中的每一行, MATCH() 傳回相關值,即, 搜尋字串和 MATCH()表中指定該行文字之間的一個相似性測量列中。
在預設狀態下, 搜尋的執行方式為不區分大小寫方式。然而,你可以透過對編入索引的列使用二進位排序方式執行區分大小寫的全文搜尋。 例如,可以向一個使用latin1字元集的欄位給定latin1_bin 的排序方式,對於全文搜尋區分大小寫。
如上述所舉例子,當MATCH()被用在一個 WHERE 語句中時,相關值是非負浮點數。零相關的意思是沒有相似性。相關性的計算是基於該行中單字的數目, 該行中獨特子的數目,資料庫中單字的總數,以及包含特殊單字的文件(行)數目。
對於自然語言全文搜索,要求MATCH() 函數中命名的列和你的表中一些FULLTEXT索引中包含的列相同。對於前述問訊, 注意,MATCH()函數(題目及全文)中所命名的欄位和文章表的FULLTEXT索引中的欄位相同。若要分別搜尋題目和全文,應該對每個欄位建立FULLTEXT索引。
或也可以執行布林搜尋或使用查詢擴充進行搜尋。
上面的例子基本上顯示瞭如何使用返回行的相關性順序漸弱的MATCH()函數。而下面的例子則展示了怎樣明確地檢索相關值。回傳行的順序是不定的,原因是 SELECT 語句不包含 WHERE或ORDER BY 子句:
mysql> SELECT id, MATCH (title,body) AGAINST ('Tutorial') -> FROM articles; +----+-----------------------------------------+ | id | MATCH (title,body) AGAINST ('Tutorial') | +----+-----------------------------------------+ | 1 | 0.65545833110809 | | 2 | 0 | | 3 | 0.66266459226608 | | 4 | 0 | | 5 | 0 | | 6 | 0 | +----+-----------------------------------------+ 6 rows in set (0.00 sec)
下面的範例則較為複雜。詢問傳回相關值,同時將行依照相關性漸弱的順序排序。要達到這個結果,你應該兩次指定MATCH(): 一次在 SELECT 清單中而另一次在 WHERE子句中。這不會造成額外的內務操作,原因是MySQL 最佳化程式註意到兩個MATCH()呼叫是相同的,因此只會啟動一次全文搜尋程式碼。
mysql> SELECT id, body, MATCH (title,body) AGAINST -> ('Security implications of running MySQL as root') AS score -> FROM articles WHERE MATCH (title,body) AGAINST -> ('Security implications of running MySQL as root'); +----+-------------------------------------+-----------------+ | id | body | score | +----+-------------------------------------+-----------------+ | 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 | | 6 | When configured properly, MySQL ... | 1.3114095926285 | +----+-------------------------------------+-----------------+ 2 rows in set (0.00 sec)
表中有2行(0.00 秒)
MySQL FULLTEXT 執行將任何單字字元原形 (字母、數字和底線部分)的序列視為一個單字。這個序列或許也包含單引號 ('),但在一行中不會超過一個。 這意味著 aaa'bbb 會被視為一個單字,而 aaa''bbb則被視為2個單字。位於單字前後的單引號會被FULLTEXT分析程式去掉; 'aaa'bbb' 會變成 aaa'bbb。
FULLTEXT分析程式會透過尋找某些分隔符號來確定單字的起始位置和結束位置,例如' ' (間隔符號)、 , (逗號)以及 . (句號)。假如單字沒有被分隔符號分開,(例如在中文裡 ), 則 FULLTEXT 分析程式不能確定一個字的起始位置和結束位置。為了能夠在這樣的語言中向FULLTEXT 索引添加單字或其它編入索引的術語,你必須對它們進行預處理,使其被一些諸如"之類的任意分隔符分隔開。
一些詞在全文搜尋會被忽略:
任何過於短的字都會被忽略。就是一個像“the” 或“some” 這樣過於平常而被認為是不具語義的詞。一個正確的單字根據其在詞庫和詢問中的重要性而被衡量。原因是在這個特別詞庫中其語義價值較低。 。
这项技术最适合同大型词库一起使用 (事实上, 此时它经过仔细的调整 )。对于很小的表,单词分布并不能充分反映它们的语义价值, 而这个模式有时可能会产生奇特的结果。例如, 虽然单词 “MySQL” 出现在文章表中的每一行,但对这个词的搜索可能得不到任何结果:
mysql> SELECT * FROM articles
-> WHERE MATCH (title,body) AGAINST ('MySQL');
找不到搜索的词(0.00 秒)
这个搜索的结果为空,原因是单词 “MySQL” 出现在至少全文的50%的行中。 因此, 它被列入停止字。对于大型数据集,使用这个操作最合适不过了----一个自然语言问询不会从一个1GB 的表每隔一行返回一次。对于小型数据集,它的用处可能比较小。
一个符合表中所有行的内容的一半的单词查找相关文档的可能性较小。事实上, 它更容易找到很多不相关的内容。我们都知道,当我们在因特网上试图使用搜索引擎寻找资料的时候,这种情况发生的频率颇高。可以推论,包含该单词的行因其所在特别数据集 而被赋予较低的语义价值。 一个给定的词有可能在一个数据集中拥有超过其50%的域值,而在另一个数据集却不然。
当你第一次尝试使用全文搜索以了解其工作过程时,这个50% 的域值提供重要的蕴涵操作:若你创建了一个表,并且只将文章的1、2行插入其中, 而文中的每个单词在所有行中出现的机率至少为 50% 。那么结果是你什么也不会搜索到。一定要插入至少3行,并且多多益善。需要绕过该50% 限制的用户可使用布尔搜索代码。
利用IN BOOLEAN MODE修改程序, MySQL 也可以执行布尔全文搜索:
mysql> SELECT * FROM articles WHERE MATCH (title,body) -> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE); +----+-----------------------+-------------------------------------+ | id | title | body | +----+-----------------------+-------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 2 | How To Use MySQL Well | After you went through a ... | | 3 | Optimizing MySQL | In this tutorial we will show ... | | 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | | 6 | MySQL Security | When configured properly, MySQL ... | +----+-----------------------+-------------------------------------+
这个问询检索所有包含单词“MySQL”的行,但不检索包含单词“YourSQL”的行。
布尔全文搜索具有以下特点:
它们不使用 50% 域值。.
它们不会按照相关性渐弱的顺序将行进行分类。你可以从上述问询结果中看到这一点:相关性最高的行是一个包含两个“MySQL” 的行,但它被列在最后的位置,而不是开头位置。
即使没有FULLTEXT,它们仍然可以工作,尽管这种方式的搜索执行的速度非常之慢。
最小单词长度全文参数和最大单词长度全文参数均适用。
停止字适用。
布尔全文搜索的性能支持以下操作符:
+
一个前导的加号表示该单词必须 出现在返回的每一行的开头位置。
-
一个前导的减号表示该单词一定不能出现在任何返回的行中。
(无操作符)
在默认状态下(当没有指定 + 或–的情况下),该单词可有可无,但含有该单词的行等级较高。这和MATCH() ... AGAINST()不使用IN BOOLEAN MODE修改程序时的运作很类似。
> <
这两个操作符用来改变一个单词对赋予某一行的相关值的影响。 > 操作符增强其影响,而 <操作符则减弱其影响。请参见下面的例子。
( )
括号用来将单词分成子表达式。括入括号的部分可以被嵌套。
~
一个前导的代字号用作否定符, 用来否定单词对该行相关性的影响。 这对于标记“noise(无用信息)”的单词很有用。包含这类单词的行较其它行等级低,但因其可能会和-号同时使用,因而不会在任何时候都派出所有无用信息行。
*
星号用作截断符。于其它符号不同的是,它应当被追加到要截断的词上。
"
一个被括入双引号的短语 (‘"’) 只和字面上包含该短语输入格式的行进行匹配。全文引擎将短语拆分成单词,在FULLTEXT索引中搜索该单词。 非单词字符不需要严密的匹配:短语搜索只要求符合搜索短语包含的单词且单词的排列顺序相同的内容。例如, "test phrase" 符合 "test, phrase"。
若索引中不存在该短语包含的单词,则结果为空。例如,若所有单词都是禁用词,或是长度都小于编入索引单词的最小长度,则结果为空。
以下例子展示了一些使用布尔全文符号的搜索字符串:
'apple banana'
寻找包含至少两个单词中的一个的行。
'+apple +juice'
寻找两个单词都包含的行。
'+apple macintosh'
寻找包含单词“apple”的行,若这些行也包含单词“macintosh”, 则列为更高等级。
'+apple -macintosh'
寻找包含单词“apple” 但不包含单词 “macintosh”的行。
'+apple +(>turnover
寻找包含单词“apple”和“turnover” 的行,或包含“apple” 和“strudel”的行 (无先后顺序),然而包含 “apple turnover”的行较包含“apple strudel”的行排列等级更为高。
'apple*'
寻找包含“apple”、“apples”、“applesauce”或“applet”的行。
'"some words"'
寻找包含原短语“some words”的行 (例如,包含“some words of wisdom” 的行,而非包含 “some noise words”的行)。注意包围词组的‘"’ 符号是界定短语的操作符字符。它们不是包围搜索字符串本身的引号。
全文搜索支持查询扩展功能 (特别是其多变的“盲查询扩展功能” )。若搜索短语的长度过短, 那么用户则需要依靠全文搜索引擎通常缺乏的内隐知识进行查询。这时,查询扩展功能通常很有用。例如, 某位搜索 “database” 一词的用户,可能认为“MySQL”、“Oracle”、“DB2” and “RDBMS”均为符合 “databases”的项,因此都应被返回。这既为内隐知识。
在下列搜索短语后添加WITH QUERY EXPANSION,激活盲查询扩展功能(即通常所说的自动相关性反馈)。它将执行两次搜索,其中第二次搜索的搜索短语是同第一次搜索时找到的少数顶层文件连接的原始搜索短语。这样,假如这些文件中的一个 含有单词 “databases” 以及单词 “MySQL”, 则第二次搜索会寻找含有单词“MySQL” 的文件,即使这些文件不包含单词 “database”。下面的例子显示了这个不同之处:
mysql> SELECT * FROM articles -> WHERE MATCH (title,body) AGAINST ('database'); +----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 1 | MySQL Tutorial | DBMS stands for DataBase ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec) mysql> SELECT * FROM articles -> WHERE MATCH (title,body) -> AGAINST ('database' WITH QUERY EXPANSION); +----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 3 | Optimizing MySQL | In this tutorial we will show ... | +----+-------------------+------------------------------------------+ 3 rows in set (0.00 sec)
另一个例子是Georges Simenon 搜索关于Maigret的书籍, 这个用户不确定“Maigret”一词的拼法。若不使用查询扩展而搜索“Megre and the reluctant witnesses” 得到的结果只能是的“Maigret and the Reluctant Witnesses” 。 而带有查询扩展的搜索会在第二遍得到带有“Maigret”一词的所有书名。
注释: 盲查询扩展功能很容易返回非相关文件而增加无用信息,因此只有在查询一个长度很短的短语时才有必要使用这项功能。
以下表列出了默认的全文停止字:
一個 | 能夠根據 | 關於 | 一個 | 能夠根據 |
以上 | 之後 | 之後 | 再次 | |
不是 | 全部 | 允許 | 允許 | |
獨自 | 是 | 當中 | ||
當中 | 一個 | 和 | 另一個 | 任何 |
任何人 | 無論如何 | 任何人 | 出現 | 欣賞 |
合適 | 是 | 不是 | 在 | 作為 |
放在一邊詢問關聯 | 可用 | 遠去 | 可怕 | 成為 |
因為 | 成為 | 成為 | 之前成為 | |
相信 | 下面 | 旁邊 | 另外 | |
更好 | 之間 | 超越 | 兩者 | |
但是 | 兩者 | 簡短 | 但是 | 兩者 |
可以 | 不能 | 不能 | ||
原因 | 原因一定 | 一定 | 來清楚 | |
一定 | 來清楚 | 來清楚 | 有關 | 因此 |
考慮 | 考慮 | 包含 | 包含 | 包含 |
對應 | 可以 | 對應 | 可以 | |
儘管 | 做了 | 沒有 | ||
做 | 做 | 做 | ||
完成每個時 | 不會向下 | 完成每個期間 | edu | |
八個 | 要么 | 其他 | 其他地方 | |
完全 | 每個人 | 每個人 | ||
每個地方 | 前 | 完全正確 | 範例 | |
完全正確 | 範例 | 五個 | 跟著 | 以下 |
跟隨 | 為 | 前 | 前 | 向前 |
得到 | 得到 | 給予 | 給予 | |
去 | 去 | 走了 | 得到了 | |
幾乎沒有 | 有 | 沒有 | 有 | |
有 | 他 | 他是 | 你好 | |
在此 | 在這裡 | 在這裡 | 她的 | |
嗨 | 他 | 他 | 如何 | |
我會 | 我會 | 我 | 我已經 | |
如果 | 如果 | |||
表示 | 表示 | 表示 | 內心 | |
相反 | 進入 | 向內 | ||
它 | 本身 | 只是 | 保持 | |
保留 | 知道 | 知道 | ||
知道 | 最後 | 最後 | 最少 | 少 |
以免 | 讓 | 讓 | 喜歡 | 喜歡 |
可能 | 喜歡 | 可能 | ||
很多 | 可能 | 也許 | 我 | |
同時 | 僅 | 可能 | 必須 | |
我自己 | 名字 | 即 | nd | |
差不多 | 需要 | 需要 | 新 | |
下一個 | 九 | 沒有 | 沒有人 | 沒有 |
沒有 | 沒有人 | 也沒有 | ||
沒什麼 | 小說 | 現在 | 無處 | 顯然 |
的 | 老 | 上 | 曾經 | 一個 |
一個 | 一個 | 或 | 其他 | |
或 | 其他 | 我們自己 | 外面 | |
結束 | 整體 | 自己 | 特別 | |
每 | 大概 | 可能 | 提供 | |
相當 | qv | 而是 | rd | |
相對 | re仔細看 | 對 | 說 | |
看到了 | 說 | 說 | 看到 | |
似乎 | 似乎 | 似乎 | 看見 | |
自己 | 懂事 | 應該 | ||
應該 | 不應該 | 因為 | 六 | 不應該因為 |
所以 | 一些 | 一些人 | ||
某處 | 很快 | 抱歉 | 指定 | |
指定 | 子 | |||
子 | 是 | 採取 | ||
告訴 | 傾向於 | 第 | 比 | |
謝謝 | 那個 | 的那個 | 那個 | |
他們的 | 他們 | 他們自己 | 然後 | |
那裡 | 那裡 | 此後 | 這些 | |
他們會 | 他們會 | 他們是 | 他們已經 | |
第三個 | 這個 | 第三個 | ||
穿過 | 整個 | 穿過 | ||
到 | 一起 | 也 | 拍了 | |
嘗試 | 嘗試 | 兩次 | 兩個 | un |
下 | 不幸 | 除非 | 下 | 不幸 |
我們 | 使用 | 用過 | ||
使用 | 用 | 通常 | 值 | |
想要 | 想要 | 是 | 不是 | |
我們 | 我們會 | 我們會 | 我們是好 | |
曾經 | 不是 | 什麼 | 什麼是 | |
何時 | 從哪裡 | 何時 | 在哪裡 | |
於是 | 無論在哪裡 | 是否 | ||
而 | 去哪裡 | 誰 | 去哪裡 | |
為什麼 | 將會 | 願意 | 願望 | |
內 | 沒有 | 不會 | ||
你 | 你會 | 你會 | 你 | |
你的 | 你的 | 你自己 | 你自己 |