MySQL-全文本搜索(学习如何使用MySQL的全文本搜索功能进行高级的数据查询。)

  并不是全部引擎都支持全文本搜索MySQL。与全部其余的DBMS同样,MySQL具备一个具体管理和处理数据的内部引擎。在你使用CREATE TABLE语句时,该引擎具体建立表,而在你使用SELECT语句或进行其它的数据库处理时,该引擎在内部处理你的请求。多数时候,该引擎都隐藏在DBMS内,不须要过多关注它。html

  但MySQL与其它的DBMS不同,它具备多种引擎。它打包多个引擎,这些引擎都隐藏在MySQL服务器内,全都能执行CREATE TABLE与SELECT命令。mysql

  为何要发行多种引擎呢?由于它们具备不一样的功能和特性,为不一样的任务选择正确的引擎得到良好的功能和灵活性。正则表达式

  固然,你能够忽略这些数据库引擎。若是省略ENGINE=语句,则使用默认引擎(极可能是MyISAM),多数SQL语句都会默认使用它。但不是全部的语句都默认使用它,这就是为何ENGINE=语句很重要的缘由。sql

  如下是几个须要知道的引擎:数据库

  1.InnoDB是一个可靠的事务处理引擎,它不支持全文本搜索。服务器

  2.MEMORY在功能等同于MyISAM,但因为数据存储在内存(不是磁盘)中,速度很快(特别适合于临时表)函数

  3.MyISAM是一个性能极高的引擎,它支持全文本搜索,但不支持事务处理。性能

  所支持引擎的完整列表(及它们之间的不一样),请参阅(http://dev.mysql.com/doc/refman/5.0/en/storage_engines.html)spa

 

  LIKE关键字,利用通配操做符匹配文本(和部分文本)。使用LIKE,可以查找包含特殊值或部分值得行(无论这些值位于列内的什么位置)。设计

  用基于文本的搜索做为正则表达式匹配列值,使用正则表达式,能够编写查找所需行的很是复杂的匹配模式。

  虽然这些搜索机制很是有用,但存在几个重要的机制。

  1.性能:通配符和正则表达式匹配一般要求MySQL尝试匹配表中全部行(并且这些搜索极少使用表索引)。所以,因为被搜索行数不断增长,这些搜索可能很是耗时。

  2.明确控制:使用通配符和正则表达式匹配,很难(并且并不老是能)明确地控制匹配什么和不匹配什么。例如,指定一个词匹配和指定一个词不匹配....

  3.智能化的结果:虽然基于通配符和正则表达式的搜索提供了很是灵活的搜索,但它们都不能提供一种智能化的选择结果的方法。例如:一个特殊词的搜索将会返回包含这些词的全部行,而不区分包含单个匹配的行和包含多个匹配的行(按照多是更好地匹配来排列它们)。相似,一个特殊词的搜索将不会找出不包含该词但包含其余相关词的行。

  全部这些限制以及更多的限制均可以用全文本搜索来解决,在使用全文本搜索时,MySQL不须要分别查看每一个行,不须要分别分析和处理每一个词。MySQL建立指定列中各词的一个索引,搜索能够针对这些词进行。这样,MySQL能够快速有效的决定那些词分配(那些行包含它们),那些词不匹配,它们匹配的频率,等等。

  使用全文本搜索

  为了进行全文本搜索,必须索引被搜索的列,并且要随着数据的改变不断从新索引。在对表列进行适当的设计后,MySQL会自动进行全部的索引和从新索引。

  在索引以后,SELECT可与Match()和Against()一块儿使用以实际执行搜索。

  启用全文本搜索

  通常在建立表时启用全文本搜索。CREATE TABLE接受FULLTEXT字句,它给出被索引列的一个逗号分隔的列表。

  下面的CREATE语句演示了FULLTEXT字句的使用:

CREATE TABLE productnotes           
(
    note_id int NOT NULL AUTO_INCREMENT,
    prod_id char(10) NOT NULL,
    note_text text NOT NULL,
    note_date datetime NOT NULL,
    PRIMARY KEY(note_id),
    FULLTEXT(note_text)
)ENGINE=MyISAM;

  这些列中有一个名为note_text的列,为了进行全文本搜索,MySQL根据字句FULLTEXT(note_text)的指示对它进行了索引,这里的FULLTEXT索引单个列,若是须要也能够指定多个列。

  在定义以后,MySQL自动维护该索引。在增长、更新或删除行时,索引随之自动更新。

  能够在建立表时指定FULLTEXT,或者在稍后指定。可是不要在导入数据时使用FULLTEXT,由于更新索引须要时间,虽然不是不少,但毕竟要花时间。若是正在导入数据到一个新表,此时不该该启用FULLTEXT索引。应该首先导入全部数据,而后在修改表,定义FULLTEXT,这要有助于更快地导入数据(并且使索引的总时间小于在导入每行每行时分别进行索引所需的总时间)。

  进行全文本搜索

  在索引以后,使用两个函数Match()和Against()函数执行全文本搜索,其中Match指定被搜索的列,Against指定要使用的搜索表达式。

SELECT note_text
 FROM productnotes
WHERE Match(note_text) Against('rabbit');

  输出:note_text

  此SELECT语句检索单个列note_text。因为WHERE子句,一个全文本搜索被执行。Match(note_text)指示MySQL针对指定的列进行搜索,Against('rabbit')指定词rabbit做为搜索文本)。因为有两行包含词rabbit,这两个行被返回。

  注意:使用完整的Match()说明,传递给Match()的值必须与FULLTEXT()定义中的相同。若是指定多个列,则必须列出它们(并且次序必须正确)。

  搜索不区分大小写,除非使用BINARY方式,不然全文本搜索不区分大小写。

  事实是刚才的搜索能够简单的用LIKE子句完成,以下所示:

SELECT note_text
FROM productnotes
WHERE note_text LIKE '%rabbit%';

  检索结果相同,可是次序不一样!(虽然并非老是出现这种状况);

  已知上述两条SELECT语句都不包含ORDER BY子句。后者(LIKE)以不特别有用的顺序返回数据。前者(使用全文本搜索)返回以文本匹配的良好程度排序的数据。两个行都包含词rabbit,但包含词rabbit做为第3个词的行的等级比做为第20个词的行高。这很重要,全文本搜索的一个重要部分就是对结果进行排序,具备较高等级的行先返回(由于这些多是你真正想要的行)。

  如何查看等级呢?以下所示:

SELECT note_text,Match(note_text) Against('rabbit') AS rank
FROM productnotes

  这里,在SELECT而不是WHERE子句中石油Match()和Against()。这使全部行都被返回(由于没有WHERE子句)。Match()和Against()用来简历一个计算列(别名为rank),此列包含全文本搜索计算出的等级值。等级由MySQL根据行的数目计算出来。正如缩减,不包含rabbit的行等级为0。确实包含rabbit的两行都有一个等级值,文本中词靠前的行等级比词靠后的行的等级值高。

  这个例子有助于说明全文本搜索如何排除行(排除那些等级为0的行),如何排序结果(按等级以降序排序)

  排序多个搜索项:若是指定多个搜索项,则包含多数匹配词的那些航将具备比包含较少词(或仅有一个匹配)的哪些行高的等级值。

  正如所见,全文本搜索提供了简单的LIKE搜索所不能提供的功能。并且,因为数据时索引的,全文本搜索还至关快

  使用查询扩展

  查询扩展是用来设法放宽所返回的全文本搜索结果的范围。在使用查询扩展时,MySQL对数据和索引进行两边扫描来完成搜索。

  1.首先,进行一个基本的全文本搜索,找出与搜索条件匹配的全部行。

  2.其次,MySQL检查这些匹配行并选择全部有用的词。(什么是有用?无用?

  3.再其次,MySQL再次进行全文本搜索,此次不只使用原来的条件,并且还使用有用的词。

  利用查询扩展,能找出全部可能相关的结果,即时它们并不精确包含全部查找的词。

  查询扩展功能是MySQL4.1.1中引入的。所以不能用于以前的版本。

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('anvils' WITH QUERY EXPANSION)

  布尔文本搜索

  MySQL支持全文本搜索的另外一种形式:称为布尔方式(boolean mode)。以布尔方式,能够提供关于以下内容的细节:

  1.要匹配的词;

  2.要排斥的词(若是某行包含这个词,则不反含该行,即时它包含其余指定的词也是如此);

  3:排列提示:(指定某些词比其它词更重要,更重要的词的等级高);

  4:表达式分组;

  5:另一些内容;

  布尔文本搜索即便没有FULLTEXT索引也可使用,布尔方式不一样于迄今为止使用的全文本搜索搜索语法的地方在于,即便没有定义FULLTEXT索引,也可使用它。但这是一种很是缓慢的操做(其性能将随着数据量的添加而下降)。

  为演示IN BOOLEAN MODE的做用,例子以下:

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('heavy' IN BOOLEAN MODE);

  此全文本搜索检索包含词heavy的全部行(有两行)。其中使用了关键字IN BOOLEAN MODE,但实际上没有指定布尔操做符,所以,其结果与没有指定布尔方式的结果相同。

  为了匹配包含heavy但不包含任意以rope开始的词的全部行,可以使用以下查询:

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE);

  咱们已经看到可两个全文本搜索布尔操做符 - 和 * ,- 排除一个词,而 * 是截断操做符(可想象为用于词尾的一个通配符)。下列所见为MySQL支持的布尔操做符:

                             全文本布尔操做符

布尔操做符 说明
+ 包含,词必须存在
- 排除,词必须不出现
> 包含,并且增长等级值
< 包含,且减小等级值
() 把词组成子表达式(容许这些子表达式做为一个组被包含、排除、排列等)
~ 取消一个词的牌谑值
* 词尾的通配符
"" 定义一个短语(与单个词的列表不同,它匹配整个短语以便包含或排除这个短语)

  

 下面举几个例子,说明这些操做符如何使用:

  

SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('+rabbit +bait' IN BOOLEAN MODE);
这个搜索匹配包含词rabbit和bait的行


SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('rabbit bait' IN BOOLEAN MODE);
没有指定操做符,这个搜索匹配包含词rabbit和bait中的至少一个词的行;


SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('“rabbit bait”' IN BOOLEAN MODE);
这个搜索匹配短语rabbit bait,而不是匹配两个词;



SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('>rabbit <carrot' IN BOOLEAN MODE);
这个搜索匹配rabbit 和carrot,增长前者的等级,下降后者的等级;


SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('+safe +(<combination)' IN BOOLEAN MODE);
这个搜索匹配safe 和combination,下降后者的等级;

  全文本搜索数据时,短词被忽略并且从索引中删除。短词定义为那些具备3个或者3个如下字符的词(若是须要,这个数目能够修改)。

  许多词出现的频率高,搜索它们没有用处(返回太多的结果),所以,MySQL定义了一条50%的规则,若是一个词出如今50%以上的行中,则将它做为一个非用词忽略。50%规则不用于IN BOOLEAN MODE

  若是表中的行数小于3行,则全文本搜索将不返回结果(由于每一个词或者不出现,或者至少出如今50%的行中)。

  忽略词中的单引号 ' 。

  尽在MyISAM的数据库引擎中支持全文本搜索。

相关文章
相关标签/搜索