全文本搜索

 一、理解全文本搜索

    MyISAM支持全文本搜索,InnoDB不支持。
    通配符与正则表达式匹配的性能较低,通常会匹配表的所有行,而且这些搜索极少使用索引,且返回的结果不智能化。在使用全文本搜索时,mysql不需要分别查看每个行,不需要分析和处理每个词。
    为了进行全文本搜索,必须在被搜索的列建立索引,在建立索引后,使用match()与against()完成搜索,match指定被搜索的列,against指定要使用的搜索表达式。传递给match()的值必须与fulltext()定义中的相同,如果指定多个列,则必须列出他们,次序也需正确。
    启用全文本搜索可以在建立表时指定,FULLTEXT(note_text),指定对该列进行索引,如果需要也可以指定多个列。如果正在导入数据到一个新表,不应该开启fulltext索引,应该先导入所有数据,然后再修改表,定义fulltext,这样有助于更快导入数据,因为如果建表时指定,mysql会自动维护索引,在增加、更新或删除行时,索引也会随之更新,会花费时间。
      全文本搜索会对结果排序,具有较高等级的行先返回,以文本匹配的良好程度排序数据。如果指定多个搜索项,则包含多数匹配词的那些行将具有比包含较少词的那些行高的等级值。全文搜索有的功能可以用LIKE实现,但是全文搜索提供了LIKE不能提供的功能(结果自动排序),而且由于数据是索引的,全文本所有还相当快。

二、使用全文搜索:

有时,我们需要使用全文本搜索,例如:要搜索文本中存在指定的某个词,且以这个词出现的顺序排序。 

先创建支持全文本搜索的表: 

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

注意:要使用全文本搜索,引擎一定要是MyISAM(ENGINE=MyISAM)。 
在note_text字段定义了全文本搜索功能后,MySQL会自动为这列添加索引,并维护该索引。在增加,更新或删除行时,索引随之自动更新。如果需要,也可以给多个列添加索引。

MYSQL中使用Match()和Against()函数进行全文本搜索。

假设product_notes表中已经有了数据,现在我们来使用全文本查询: 

SELECT note_text FROM product_notes WHERE Match(note_text) Against(‘rabbit’); 
这条语句检索出note_text字段包含rabbit的行。类似于: 
SELECT note_text FROM product_notes WHERE note_text like ‘%rabbit%’; 

两者的区别在于使用like查询仅仅只返回包含‘rabbit’的行,而使用全文本会按’rabbit’在文本中出现的顺序排序,这是like所做不到的。例如(假设note_text字段存在两行包含rabbit的行): 
1:A fat rabbit 
2:A rabbit 
用全文本搜索出来就的排序就会这样 
2:A rabbit 
1:A fat rabbit 
因为2中的rabbit前面只有一个词,而1中的有两个,所以2的优先级高,自然排在前面。 
但是LIKE关键字返回的结果只是按默认的排序规则。
SELECT note_text FROM product_notes WHERE note_text like ‘%rabbit%’; 
SELECT note_text FROM product_notes WHERE Match(note_text) Against(‘rabbit’); 

如何查看优先级?一般是按照搜索值在行中的前后顺序排列的,搜索的关键词在本行中越靠前等级越高。当然我们可以用代码查看:

SELECT note_text,Match(note_text) Against(‘rabbit’) AS rank FROM product_notes;
返回: 
note_text rank 
1:A fat rabbit 1.5935389274914 
2:A rabbit 1.6403435232543 
3:A good day 0 

4:To do it 0

由此我们可以看出,不包含关键字rabbit的行的等级为0,包含rabbit关键字的,rabbit越靠前,等级越高。 

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

三、使用查询扩展:

SELECT note_text FROM product_notes WHERE Match(note_text) Against('rabbit' WITH QUERY EXPANSION); 
返回: 
2:A rabbit 
1:A fat rabbit 
3:A good day 
查询扩展用来设法放宽所返回的全文本搜索结果的范围。 
因为3存在一个A(依赖于1和2中的A,即会把相关的行返回回来,类似于有一行里面包含thinkphp和tp关键字,当你用查询扩展查询thinkphp时,仅仅包含tp的行也会返回回来),所以也被查询出来了。 

查询扩展极大的增加了返回的行数,但这样做实际上增加了你可能并不想要的数据,另外,表中的行数越多,使用查询扩展返回的结果就会越好!因此,请酌情使用。

四、布尔文本搜索:

布尔操作符 描述 
+ 包含指定值 
- 排除指定值 
> 包含指定值,并且增加优先级值 
< 包含指定值,并且减少优先级值 
() 把词组成表达式 
~ 取消一个词的排序值 
* 词尾的通配符 

" "定义一个短语 

注意:要排斥的词Against(‘xxx -排斥词’ IN BOOLEAN MODE),如果某行包含这个词,则不返回该行,即使它包含所要匹配的词也不可以。

例如:

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

它表示排除了包含rope*(任何以rope开始的词)的行,虽说第一行里含有heavy,但由于含有rope,所以要剔除。

下面给出一些例子:
SELECT note_text FROM  product_notes  WHERE Match(note_text) Against('+rabbit +fat' IN BOOLEAN MODE);
返回: 
2:A fat rabbit 

返回的行必须同时包含关键字 rabbit 和 fat(rabbit 和fat不用连在一起)

SELECT note_text  FROM product_notes  WHERE Match(note_text) Against('“rabbit fat”' IN BOOLEAN MODE); 
返回: 
2:A fat rabbit 

文本包含”fat rabbit”的行(现在关键字是这个短语“fat rabbit”)。

SELECT note_text  FROM product_notes  WHERE Match(note_text) Against('+fat +(>rabbit)' IN BOOLEAN MODE); 
返回: 
2:A fat rabbit 

文本包含fat和rabbit的行,且增加后者的优先级值。

五、全文本搜索使用说明:

1、指定值出现在行中的频率少于50% (频率太高,返回结果太多,没用) ;
2、忽略MySQL的内建非用词(stopword) ;
3、忽略单引号,如:don’t 搜索为dont ;
4、不具有词分隔符的语言(如:日语和汉语)不能恰当地返回全文本搜索结果 ;
5、引擎必须是MyISAM类型。

猜你喜欢

转载自blog.csdn.net/wangjian530/article/details/80554785