18.1 理解全文本搜索
并非所有引擎都支持全文本搜索,MyISAM支持,InnoDB不支持
LINK关键字,利用通配操作符匹配文本
使用正则表达式,可以编写查找所需行的非常复杂的匹配模式
以上搜索机制存在几个重要的限制。
性能:尝试匹配表中所有行,由于被搜索行数不断增加,搜索可能非常耗时明确控制:很难明确控制匹配什么和不匹配什么智能化的结果:不能提供一种智能化的选择结果的方法
使用全文本搜索可以解决以上限制
18.2 使用全文本搜索
必须索引被搜索的列,而且要随着数据的改变不断地重新索引。在索引之后,SELECT可与Match()和Against()一起使用以实际执行搜索
18.2.1 启用全文本搜索支持
一般在创建表时启用全文本搜索。CREATE TABLE语句接受FULLTEXT子句,它给出被索引列的一个逗号分割的列表。
CREATE TABLE productnotes{note_id int NOT NULL AUTO_INCREMENT,prod_id char(10) NOT NULL,note_date datetimeNOT NULL,note_text textNULL,PRIMARY KEY(note_id),FULLTEXT(note_text)}ENGINE=MyISAM;
MySQL根据子句FULLTEXT(note_text)的指示对它进行索引。在定义之后,MySQL自动维护该索引,在增加、更新或删除行时,索引随之自动更新。
不要在导入数据时使用FULLTEXT,应该首先导入所有数据,然后再修改表,定义FULLTEXT。
18.2.2 进行全文本搜索
在索引之后,使用两个函数Match()和Against()执行全文本搜索,Match()指定被搜索的列,Against()指定要使用的搜索表达式。
SELECT note_textFROM productnotesWHERE Match(note_text) Against('rabbit');
传递给Match()的值必须与FULLTEXT()定义中的相同。如果指定多个列,则必须列出它们(而且次序正确)
除非使用BINARY方式,否则全文本搜索不区分大小写
使用LINK子句实现
SELECT note_textFROM productnotesWHERE note_text LINK '%rabbit%';
全文本搜索对结果排序,具有较高等级的行先返回。
使用下例演示排序如何工作
SELECT note_text,Match(note_text) Against('rabbit') AS ranksFROM productnotes;
在SELECT而不是WHERE子句中使用Match()和Against()。所有行都会被返回,Match()和Against()用来建立一个计算列,此列包含全文本搜索计算出的等级值。
等级由MySQL根据行中词的数目,唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来。
如果指定多个搜索项,则包含多数匹配词的那些行将具有比包含较少词的那些行高的等级值。
18.2.3 使用查询扩展
在使用查询扩展时,MySQL对数据和索引进行两边扫描来完成搜索:
首先,进行一个基本的全文本搜索,找出与搜索条件匹配的所有行其次,MySQL检查这些匹配行并选择所有有用的词再其次,MySQL再次进行全文本搜索,这次不仅使用原来的条件,而且还使用所有有用的词
没有查询扩展的简单全文本搜索
SELECT note_textFROM productnotesWHERE Match(note_text) Against('anvils');
使用查询扩展
SELECT note_textFROM productnotesWHERE Match(note_text) Against('anvils' WITH QUERY EXPANSION);
18.2.4 布尔文本搜索
要匹配的词/要排斥的词/排列提示/表达式分组/另外一些内容
即使没有FULLTEXT索引也可以使用
SELECT note_textFROM productnotesWHERE Match(note_text) Against('heavy' IN BOOLEAN MODE);
全文本布尔操作符
+:包含,词必须存在-:排除,词必须不出现大于号:包含,而且增加等级值小于号:包含,且减少等级值():把词组成子表达式(允许这些子表达式作为一个组被包含、排除、排列等)~:取消一个词的排序值*:词尾的通配符”“:定义一个短语(与单个词的列表不一样,它匹配整个短语以便包含或排除这个短语)
下面搜索匹配包含词rabbit和bait的行
SELECT note_textFROM productnotesWHERE Match(note_text) Against('+rabbit +bait' IN BOOLEAN MODE);
下面搜索匹配包含词rabbit和bait中的至少一个词的行
SELECT note_textFROM productnotesWHERE Match(note_text) Against('rabbit bait' IN BOOLEAN MODE);
下面搜索匹配短语rabbit bait
SELECT note_textFROM productnotesWHERE Match(note_text) Against('"rabbit bait"' IN BOOLEAN MODE);
下面搜索匹配rabbit和carrot,增加前者的等级,降低后者的等级
SELECT note_textFROM productnotesWHERE Match(note_text) Against('>rabbit <carrot' IN BOOLEAN MODE);
下面搜索匹配safe和combination,降低后者的等级
SELECT note_textFROM productnotesWHERE Match(note_text) Against('+rabbit +(<combination)' IN BOOLEAN MODE);
排列而不排序