深入学习mysql数据库的内置函数实现全文搜索
MySQL中是支持全文搜索和索引功能的,一般在mysql数据库中的全文索引以及搜索功能,都需要就是通过mysql数据库的内置函数来实现,那么怎样进行mysql内置函数来实现数据库中的全文搜索呢?
MySQL支持全文索引和搜索功能。MySQL中的全文索引类型FULLTEXT的索引。FULLTEXT索引仅可用于MyISAM表;他们可以从CHAR、VARCHAR或TEXT列中作为CREATETABLE语句的一部分被创建,或是随后使用ALTERTABLE或CREATEINDEX被添加。对于较大的数据集,将你的资料输入一个没有FULLTEXT索引的表中,然后创建索引,其速度比把资料输入现有FULLTEXT索引的速度更为快。
全文搜索同MATCH()函数一起执行。
mysql>CREATETABLEarticles(
->idINTUNSIGNEDAUTO_INCREMENTNOTNULLPRIMARYKEY,
->titleVARCHAR(200),
->bodyTEXT,
->FULLTEXT(title,body)
->);
QueryOK,0rowsaffected(0.00sec)
mysql>INSERTINTOarticles(title,body)VALUES
->('MySQLTutorial','DBMSstandsforDataBase…'),
->('HowToUSEMySQLWell','Afteryouwentthrougha…'),
->('OptimizingMySQL','Inthistutorialwewillshow…'),
->('1001MySQLTricks','1.Neverrunmysqldasroot.2….'),
->('MySQLvs.YourSQL','Inthefollowingdatabasecomparison…'),
->('MySQLSecurity','Whenconfiguredproperly,MySQL…');
QueryOK,6rowsaffected(0.00sec)
Records:6Duplicates:0Warnings:0
mysql>SELECT*FROMarticles
->WHEREMATCH(title,body)AGAINST('database');
+—-+——————-+——————————————+
|id|title|body|
+—-+——————-+——————————————+
|5|MySQLvs.YourSQL|Inthefollowingdatabasecomparison…|
|1|MySQLTutorial|DBMSstandsforDataBase…|
+—-+——————-+——————————————+
2rowsinset(0.00sec)
MATCH()函数对于一个字符串执行资料库内的自然语言搜索。一个资料库就是1套1个或2个包含在FULLTEXT内的列。搜索字符串作为对AGAINST()的参数而被给定。对于表中的每一行,MATCH()返回一个相关值,即,搜索字符串和MATCH()表中指定列中该行文字之间的一个相似性度量。
在默认状态下,搜索的执行方式为不区分大小写方式。然而,你可以通过对编入索引的列使用二进制排序方式执行区分大小写的全文搜索。例如,可以向一个使用latin1字符集的列给定latin1_bin的排序方式,对于全文搜索区分大小写。
如上述所举例子,当MATCH()被用在一个WHERE语句中时,相关值是非负浮点数。零相关的意思是没有相似性。相关性的计算是基于该行中单词的数目,该行中独特子的数目,资料库中单词的总数,以及包含特殊词的文件(行)数目。
对于自然语言全文搜索,要求MATCH()函数中命名的列和你的表中一些FULLTEXT索引中包含的列相同。对于前述问讯,注意,MATCH()函数(题目及全文)中所命名的列和文章表的FULLTEXT索引中的列相同。若要分别搜索题目和全文,应该对每个列创建FULLTEXT索引。
或者也可以运行布尔搜索或使用查询扩展进行搜索。
上面的例子基本上展示了怎样使用返回行的相关性顺序渐弱的MATCH()函数。而下面的例子则展示了怎样明确地检索相关值。返回行的顺序是不定的,原因是SELECT语句不包含WHERE或ORDERBY子句:
mysql>SELECTid,MATCH(title,body)AGAINST('Tutorial')
->FROMarticles;
+—-+—————————————–+
|id|MATCH(title,body)AGAINST('Tutorial')|
+—-+—————————————–+
|1|0.65545833110809|
|2|0|
|3|0.66266459226608|
|4|0|
|5|0|
|6|0|
+—-+—————————————–+
6rowsinset(0.00sec)
下面的例子则更加复杂。询问返回相关值,同时对行按照相关性渐弱的顺序进行排序。为实现这个结果,你应该两次指定MATCH():一次在SELECT列表中而另一次在WHERE子句中。这不会引起额外的内务操作,原因是MySQL优化程序注意到两个MATCH()调用是相同的,从而只会激活一次全文搜索代码。
mysql>SELECTid,body,MATCH(title,body)AGAINST
->('SecurityimplicationsofrunningMySQLasroot')ASscore
->FROMarticlesWHEREMATCH(title,body)AGAINST
->('SecurityimplicationsofrunningMySQLasroot');
+—-+————————————-+—————–+
|id|body|score|
+—-+————————————-+—————–+
|4|1.Neverrunmysqldasroot.2….|1.5219271183014|
|6|Whenconfiguredproperly,MySQL…|1.3114095926285|
+—-+————————————-+—————–+
2rowsinset(0.00sec)
表中有2行(0.00秒)
#p#分页标题#e#
MySQLFULLTEXT执行将任何单字字符原形(字母、数字和下划线部分)的序列视为一个单词。这个序列或许也包含单引号('),但在一行中不会超过一个。这意味着aaa'bbb会被视为一个单词,而aaa''bbb则被视为2个单词。位于单词之前或其后的单引号会被FULLTEXT分析程序去掉;'aaa'bbb'会变成aaa'bbb。
FULLTEXT分析程序会通过寻找某些分隔符来确定单词的起始位置和结束位置,例如''(间隔符号)、,(逗号)以及.(句号)。假如单词没有被分隔符分开,(例如在中文里),则FULLTEXT分析程序不能确定一个词的起始位置和结束位置。为了能够在这样的语言中向FULLTEXT索引添加单词或其它编入索引的术语,你必须对它们进行预处理,使其被一些诸如”之类的任意分隔符分隔开。
一些词在全文搜索中会被忽略:
◆任何过于短的词都会被忽略。全文搜索所能找到的词的默认最小长度为4个字符。
◆停止字中的词会被忽略。禁用词就是一个像“the”或“some”这样过于平常而被认为是不具语义的词。存在一个内置的停止字,但它可以通过用户自定义列表被改写。
词库和询问中每一个正确的单词根据其在词库和询问中的重要性而被衡量。通过这种方式,一个出现在许多文件中的单词具有较低的重要性(而且甚至很多单词的重要性为零),原因是在这个特别词库中其语义价值较低。反之,假如这个单词比较少见,那么它会得到一个较高的重要性。然后单词的重要性被组合,从而用来计算该行的相关性。
这项技术最适合同大型词库一起使用(事实上,此时它经过仔细的调整)。对于很小的表,单词分布并不能充分反映它们的语义价值,而这个模式有时可能会产生奇特的结果。例如,虽然单词“MySQL”出现在文章表中的每一行,但对这个词的搜索可能得不到任何结果:
mysql>SELECT*FROMarticles
->WHEREMATCH(title,body)AGAINST('MySQL');
找不到搜索的词(0.00秒)
这个搜索的结果为空,原因是单词“MySQL”出现在至少全文的50%的行中。因此,它被列入停止字。对于大型数据集,使用这个操作最合适不过了—-一个自然语言问询不会从一个1GB的表每隔一行返回一次。对于小型数据集,它的用处可能比较小。
一个符合表中所有行的内容的一半的单词查找相关文档的可能性较小。事实上,它更容易找到很多不相关的内容。我们都知道,当我们在因特网上试图使用搜索引擎寻找资料的时候,这种情况发生的频率颇高。可以推论,包含该单词的行因其所在特别数据集而被赋予较低的语义价值。一个给定的词有可能在一个数据集中拥有超过其50%的域值,而在另一个数据集却不然。
当你第一次尝试使用全文搜索以了解其工作过程时,这个50%的域值提供重要的蕴涵操作:若你创建了一个表,并且只将文章的1、2行插入其中,而文中的每个单词在所有行中出现的机率至少为50%。那么结果是你什么也不会搜索到。一定要插入至少3行,并且多多益善。需要绕过该50%限制的用户可使用布尔搜索代码。