使用全文本搜索功能进行高级的数据查询和选择。
mysql支持集中基本的数据库引擎,并非所有的引擎都支持本书所描述的全文本搜索,两个最常用的引擎为MyISAM
和InnoDB,前者支持全文本搜索,而后者不支持。
开始使用的like关键字,它利用通配操作符匹配文本(和部分文本)。使用like,能够查找包含特殊值或部分值的行(
不管这些值位于列内什么位置)
但like和正则表达式却有些限制:
1):性能--通配符和正则表达式匹配通常要求MySQL尝试匹配表中所有行(并不是所有列都有索引),因此,当搜索行
数量很庞大是,这样的搜索可能非常耗时。
2):明确控制--使用通配符和正则表达式匹配,很难明确的控制匹配什么和不匹配什么。例如,指定一个此必须匹配,一个词
必须不匹配,而一个词仅在第一个词确实匹配情况下才可以匹配或者才可以不匹配。
3):智能化的结果--虽然通配符和正则表达式的搜索提供了非常灵活的搜索,但他们都不能提供一个智能化的选择结果的方法。
例如,一个特殊词的搜索将会返回包含该词的所有行,而不区分包含单个匹配的行和包含多个匹配的行。类似,一个特殊词的搜索
将不会找出不包含该词但包含其他相关词的行。
这是就引入了全文本搜索:
为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引,再对表列进行适当设计后,MySQL会自动进行所有的索引
和重新索引。
首先看个例子
create table productnotes(
note_id int not null auto_increment,
prod_id char(10) not null,
note_date datetime not null,
note_text text null,
primary key(note_id),
fulltext(note_text)
)engine=MyISAM;
如上,表中有一个名为note_text的列,为了进行全文本搜索,通过子句fulltext(note_text)指示对它的索引。
这里fulltext索引单个列,如果需要也可以指定多个列。
1、默认的方式进行全文本搜索:
select note_text
from productnotes
where match(note_text) against('rabbit');
如上,在索引之后,使用两个函数match()和against()执行全文本搜索,
其中match()指定被搜索的列,against()指定要搜索的表达式。
在against()方式上,除非使用BINARY方式,否则搜索不区分大小写。
当全文本搜索时,一个重要的部分是对结果进行排序,具有较高等级的优先返回
(因为这些行可能是你真正想要的行)
例如通过下面语句可以直接诶把等级排序显示出来:
select note_text, match(note_text) against(rabbit) as rank
from productnotes ;
2、使用扩展方式查询。
查询扩展用来设法放宽所返回的全文本搜索结果的范围。考虑下面的情况,你想找出所有提到anvils的注释。
只有一个注释包含词anvils,但你还想找出可能与你的搜索有关的所有其他行,即使他们不包含词anvils。
这样是查询扩展的一项业务,在使用查询扩展时,Mysql对数据和索引进行两边扫描来完成搜索:
首先):进行一个基本的全文本搜索,找出与搜索条件匹配的所有行;
其次):mysql检查这些匹配行并选择所有有用的词;
最后):mysql再次进行全文本搜索,这次不仅使用原来的条件,而且还使用所有有用的词;
例如下面这条语句:
select note_text
from productnotes
where match(note_text) against('anvils' with query expansion);
这样返回的数据行可能不包含anvils的行也会被返回回来,但是总有一些会与包含anvils行的数据相关联,
所以才会被返回。
3、使用布尔文本搜索
使用布尔方式文本搜索是,可以提供如下的一些细节:
#要匹配的词
#要排斥的词(如果某行包含这个词,则不凡会该行,即使它包含了其他指定的词)
#排列提示(指定某些词比其他词更重要,更重要的词等级更高)
#表达式分组
#另外一些内容
先看一个简单例子:
select note_text
from productnotes
where match(note_text) against('heavy' in boolean mode);
上述因为没有指定其他的细节条件,所以这样方式搜索出的和第一种默认方式在相同条件下
检索出来数据是相同的。
另外,布尔方式还有个特点,即使没有fulltext索引,也可以使用它,但是将非常的缓慢,即性能
随着数据量增加而降低。
下面列出了全文本布尔操作符
+:包含词必须存在
-:排除,词必须不出现
>:包含,而且增加等级值
<:包含,且减少等级值
():把词组成子表达式(允许这些子表达式作为一个组被包含、排除、排列等)
~:取消一个词的排序值
*:词尾的通配符
"":定义一个短语(与单个词的列表不一样,它匹配整个短语以便包含或排除这个短语)
例如下面一些具体例子:
1):
select note_text
from productnotes
where match(note_text) against('+rabbit +bait' in boolean mode);
这个搜索匹配包含rabbit和bait的行
2):
select note_text
from productnotes
where match(note_text) against('rabbit bait' in boolean mode);
这个搜索匹配包含rabbit和bait至少一个词的行
3):
select note_text
from productnotes
where match(note_text) against('"rabbit bait"' in boolean mode);
这个搜索匹配rabbit bait短语而不是两个单独的词
4):
select note_text
from productnotes
where match(note_text) against('>rabbit <bait' in boolean mode);
这个搜索匹配包含rabbit和bait,增加前者等级,降低后者等级。
5):
select note_text
from productnotes
where match(note_text) against('+rabbit +(<bait)' in boolean mode);
这个搜索匹配包含rabbit和bait的行,但是仅仅降低后者等级。
注:由前面可知,等级可以影响结果的排序。