【MySQL必知必会】学习笔记Day9

【MySQL必知必会】学习笔记Day9&2.12&D18章&P119-130页

16、全文本搜索

(1)理解全文本搜索

在使用全文本搜索时,MySQL不需要分别查看每个行,不需要分别分析和处理每个词。MySQL创建指定列中各词的一个索引,搜索可以针对这些词进行。这样,MySQL可以快速有效地决定哪些词匹配(哪些行包含它们), 哪些词不匹配,它们匹配的频率,等等

(2)使用全文本搜索

为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引。在对表列进行适当设计后,MySQL会自动进行所有 的索引和重新索引。
在索引之后,SELECT可与Match()和Against()一起使用以实际执行搜索。

① 启用全文本搜索支持

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=My ISAM;
  • 上述列中有一个名为note_text的列,为了进行全文本搜索,MySQL根据子句FULLTEXT(note_text)的指示列对它进行索引。
  • MySQL自动维护该索引,在增加、更新或删除行时,索引随之自动更新。
    注:不要在导入数据时使用索引

②进行全文本搜索

  • 在索引之后,使用两个函数Match()和Against()执行全文本搜索
  • 其中Match()指定被搜索的列Against()指定要使用的搜索表达式
SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('rabbit');

输出:
note_text
I like rabbit
rabbit is so cute

  • 此SELECT语句检索单个列note_text。由于WHERE子句,一个全文本搜索被执行
  • Match(note_text)指示MySQL针对指定的 列进行搜索
  • Against(‘rabbit’)指定词rabbit作为搜索文本

注:使用完整的Match()说明传递给Match()的值必须与 FULLTEXT()定义中的相同。如果指定多个列,则必须列出它们(而且次序正确)。另:除非使用BINARY方式, 否则全文本搜索不区分大小写。

  • 上面语句也可以用下面的:
SELECT note_text
FROM productnotes
WHERE note_text LIKE '%rabbits%';

二者区别为:前者(使用全文本搜索)返回以文本匹配的良好程度排序的数据。两个行都包含词rabbit,但包含词rabbit作为 第3个词的行的等级比作为第20个词的行高。这很重要。全文本搜索的一 个重要部分就是对结果排序。具有较高等级的行先返回(因为这些行很 可能是你真正想要的行)。

  • eg:
SELECT note_text,
       Match(note_text) Against('rabbit') AS rank
FROM procedures;

这里,在SELECT而不是WHERE子句中使用Match()和Against()。这使所有行都被返回(因为没有WHERE子句)。Match()和Against() 用来建立一个计算列(别名为rank),此列包含全文本搜索计算出的等级值。等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的 总数以及包含该词的行的数目计算出来。正如所见,不包含词rabbit的 行等级为0(因此不被前一例子中的WHERE子句选择)。确实包含词rabbit 的两个行每行都有一个等级值,文本中词靠前的行的等级值比词靠后的 行的等级值高。

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

③ 使用查询扩展

  • 首先,进行一个基本的全文本搜索,找出与搜索条件匹配的所有 行;
  • 其次,MySQL检查这些匹配行并选择所有有用的词
  • 再其次,MySQL再次进行全文本搜索,这次不仅使用原来的条件, 而且还使用所有有用的词
SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('anvils');

上面结果返回1行

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

上面结果返回7行

查询扩展增加了返回的行数,但也增加了实际上并不想要的行的数目

注:表中的行越多(这些行中的文本就越多),使用 查询扩展返回的结果越好

④ 布尔文本搜索
MySQL支持全文本搜索的另外一种形式,称为布尔方式。以布尔方式,可以提供关于如下内容的细节:

  • 要匹配的词
  • 要排斥的词(如果某行包含这个词,则不返回该行,即使它包含其他指定的词也是如此);
  • 排列提示(指定某些词比其他词更重要,更重要的词等级更高);
  • 表达式分组;
  • 另外一些内容

注:即使没有FULLTEXT索引也可以使用布尔文文本搜索,但是会随着数据量的增加而降低性能

  • eg:
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);

这次只返回一行。这一次仍然匹配词heavy,但-rope明确地
指示MySQL排除包含rope
(任何以rope开始的词,包括 ropes)的行

如上两个全文本搜索布尔操作符-和*,- 排除一个词,而* * 是截断操作符(可想象为用于词尾的一个通配符)。

下列出支持的所有全文本布尔操作符:

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

  • eg:这个搜索匹配包含词rabbit和bait的行
SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('+rabbit +bait' IN BOOLEAN MODE);
  • eg:没有指定操作符,这个搜索匹配包含rabbit和bait中的至少一个词的行
SELECT note_text
FROM productnotes
WHERE Match(note_text) Against('rabbit bait' IN BOOLEAN MODE);
  • eg:这个搜索匹配短语rabbit bait而不是匹配两个词rabbit和 bait
SELECT note_text
FROM productnotes
WHERE Match(note_text) Against(' "rabbit bait" ' IN BOOLEAN MODE);
  • eg:匹配rabbit和carrot,增加前者的等级,降低后者的等级
SELECT note_text
FROM productnotes
WHERE Match(note_text) Against(' >rabbit 
  • eg:匹配safe 和combination,降低后者的等级
SELECT note_text
FROM productnotes
WHERE Match(note_text) Against(' +safe +(

注:在布尔方式中,不按等级值降序排序返回的行。

⑤ 全文本搜索的使用说明

  • 在索引全文本数据时,短词(具有3个或3个以下字符的词)被忽略且从索引中排除。(如需要,这个数目可以更改)
  • MySQL带有一个内建的非用词(stopword)列表,这些词在索引全文本数据时总是被忽略。如需要,可以覆盖这个列表
  • 许多词出现的频率很高,搜索它们没有用处,因此MySQL规定了一条50%规则,如果一个词出现在50%以上 的行中,则将它作为一个非用词忽略。50%规则不用于IN BOOLEAN MODE。
  • 如果表中的行数少于3行,则全文本搜索不返回结果
  • 忽略词中的单引号。例如,don’t索引为dont。
  • 不具有词分隔符(包括日语和汉语)的语言不能恰当地返回全文本搜索结果。
  • 如前所述,仅在MyISAM数据库引擎中支持全文本搜索。

【MySQL必知必会】系列笔记:
【MySQL必知必会1-4章】学习笔记Day1
【MySQL必知必会5-7章】学习笔记Day2
【MySQL必知必会8-9章】学习笔记Day3
【MySQL必知必会10章】学习笔记Day4
【MySQL必知必会11-12章】学习笔记Day5
【MySQL必知必会13章】学习笔记Day6
【MySQL必知必会14-16章】学习笔记Day7
【MySQL必知必会17章】学习笔记Day8

你可能感兴趣的:(数据库)