MySQL -- 全文检索(自然语言全文检索)
自然语言全文本检索
缺省或者modifier被设置为in natural language mode,都是进行自然语言检索。对于表中的每一行,match()都会返回一个关联值。
mysql> CREATE TABLE articles (
-> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> title VARCHAR(200),
-> body TEXT,
-> FULLTEXT ( title , body )
-> ) ENGINE=INNODB;
Query OK, 0 rows affected (0.04 sec) mysql> INSERT INTO articles (title,body) VALUES
-> ('MySQL Tutorial','DBMS stands for DataBase ...'),
-> ('How To Use MySQL Well','After you went through a ...'),
-> ('Optimizing MySQL','In this tutorial we will show ...'),
-> ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
-> ('MySQL vs. YourSQL','In the following database comparison ...'),
-> ('MySQL Security','When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0 mysql> select * from articles
-> where match(title,body)
-> against('database' in natural language mode);
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec) mysql>
缺省情况下,检索是大小写不敏感的。如果要想进行大小写敏感的检索,对于索引的列要进行二进制collation。比如字符集类型为latin1的列可以修改为Latin1_bin。
当match()被作为where子句的时候,返回的行会被自动排序,根据检索关联度进行排序。
mysql> INSERT INTO articles (title,body) VALUES
-> ('oracle Tutorial','DBMS stands for DataBase ...DataBase');
Query OK, 1 row affected (0.00 sec) mysql> select * from articles
-> where match(title,body)
-> against('database' in natural language mode);
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 7 | oracle Tutorial | DBMS stands for DataBase ...DataBase |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
3 rows in set (0.00 sec) mysql>
可以查看一下匹配的次数:
#使用索引
mysql> SELECT
-> COUNT(*)
-> FROM
-> articles
-> WHERE
-> MATCH (title , body) AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----------+
| COUNT(*) |
+----------+
| 2 |
+----------+
1 row in set (0.00 sec) mysql> #使用全表扫描
mysql> SELECT
-> COUNT(IF(MATCH (title , body) AGAINST ('database' IN NATURAL LANGUAGE MODE),
-> 1,
-> NULL)) AS count
-> FROM
-> articles;
+-------+
| count |
+-------+
| 3 |
+-------+
1 row in set (0.00 sec) mysql>
对于自然语言全文本检索,match()中的列名必须和全文索引中的列相同。上例中,如果想对title或body分开检索,就需要分别创建全文索引。
上面的例子中,基本展示了如何使用match()。返回的结果根据关联值的降序排列。
下面的例子,展示如何显式输出关联值得大小。返回的行不是有序的,因为select语句既不包含where也没有order by。
mysql> SELECT
-> id,
-> MATCH (title , body) AGAINST ('database' IN NATURAL LANGUAGE MODE) AS score
-> FROM
-> articles;
+----+---------------------+
| id | score |
+----+---------------------+
| 1 | 0.22764469683170319 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 0.22764469683170319 |
| 6 | 0 |
+----+---------------------+
6 rows in set (0.00 sec) mysql>
下面的例子更复杂,查询返回关联值得具体值,同时进行降序排序。为了实现这个目的,使用了match()两次。这样的语句不会有额外的开销,优化器会注意到两次match()调用是一样的,所以只会执行全文检索一次。
mysql> SELECT
-> id,
-> body,
-> MATCH (title , body) AGAINST ('Security implications of running MySQL as root' IN NATURAL LANGUAGE MODE) AS score
-> FROM
-> articles
-> WHERE
-> MATCH (title , body) AGAINST ('Security implications of running MySQL as root' IN NATURAL LANGUAGE MODE);
+----+------------------------------------------+----------------------------+
| id | body | score |
+----+------------------------------------------+----------------------------+
| 4 | 1. Never run mysqld as root. 2. ... | 0.6055193543434143 |
| 6 | When configured properly, MySQL ... | 0.6055193543434143 |
| 1 | DBMS stands for DataBase ... | 0.000000001885928302414186 |
| 2 | After you went through a ... | 0.000000001885928302414186 |
| 3 | In this tutorial we will show ... | 0.000000001885928302414186 |
| 5 | In the following database comparison ... | 0.000000001885928302414186 |
+----+------------------------------------------+----------------------------+
6 rows in set (0.00 sec) mysql>
用双引号引起来的词组,检索匹配的结果只能是双引号中的字面值。全文检索会将双引号中的内容分解成单词,然后执行检索匹配。非单词字符是不需要匹配的,只是按照其中的单词顺序进行匹配,比如"test phrase"和"test, phrase"是匹配的。
全文检索会将字母、数字、下划线的组合当成一个word。但是也会将'当成一个word序列,不过一行只能有一个',比如会将aaa'bbb当成一个单词,但是aaa''bbb就不是一个单词了,而是两个。如果'放在开头或者结果,会被丢弃。
内嵌的文本解释器决定单词的开头和结尾,根据delimiter符号进行判断,比如逗号、空格、点号。如果不是根据delimiter分割的,比如中文,解释器就无法判断出单词的开头和结尾了。
所以,用户必须使用某些delimiter对文本进行处理后再检索。在5.7.6中可以使用插件ngram解释器来实现对中文、日文、韩文的支持,或者使用MeCab解释器来支持日文。
也可以自己编写插件解释器。示例代码位于plugin/fulltext目录。
在全文检索中,有些单词是被忽略的:
--太短的单词。默认最小长度是3个字符(innodb)、4个字符(myisam)。可以设置innodb中的innodb_ft_min_token_size、myisam中的ft_min_word_len
--stopword中的单词会被忽略。stopword是指那些类似the、some一样太普通以致被认为是没有什么语义值得单词。有一个内嵌stopword列表。也可以重新定义。
每个正确的单词在查询时都被会加权,根据其在集合和查询中的重要性。所以出现频率越高,权重就越低。单词的权重会被用来计算行的关联值。
全文检索如果本生行数就比较少,可能检索不出正确的结果。
MySQL -- 全文检索(自然语言全文检索)的更多相关文章
- Mysql 如何实现全文检索,关键词跑分
一.前言 今天一个同事问我,如何使用 Mysql 实现类似于 ElasticSearch 的全文检索功能,并且对检索关键词跑分?我当时脑子里立马产生了疑问?为啥不直接用es呢?简单好用还贼快.但是听他 ...
- mysql 自带全文检索
对于一些简单的检索可以通过mysql自带的全文索引及 MATCH AGAINST 查询语句实现.实验步骤如下.1.建表DROP table IF exists con_video_file_des_t ...
- Mysql支持中文全文检索的插件mysqlcft-应用中的问题
MySQL目前版本的全文检索没有对中文很好的支持,但可以通过安装mysqlcft插件来实现,具体的安装使用方法:http://blog.s135.com/post/356/ mysqlcft的官方网站 ...
- MySQL -- 全文检索(布尔全文检索)
modifier的值为in boolean mode的时候,可以使用布尔全文检索.在布尔全文检索中,有些字符在检索字符串的开头或结尾会有特殊含义.在下面的示例中,+和-操作符表明在匹配的时候,单词必须 ...
- MySQL中InnoDB全文检索
InnoDB存储引擎从1.2.x开始支持全文索引技术,其采用full inverted index的方式.在InnoDB存储引擎中,将(DocumentID,Postition)视为一个ilist.因 ...
- php + mysql + sphinx 的全文检索(2)
简单 使用php api 去查询 sphinx 的索引数据 $sphinx = new SphinxClient(); $sphinx->SetServer ( ...
- MySQL 5.7 中文全文检索
MySQL 5.7 中文全文检索 在 MySQL 5.7.6 之前,全文索引只支持英文全文索引,不支持中文全文索引,需要利用分词器把中文段落预处理拆分成单词,然后存入数据库.从 MySQL 5.7.6 ...
- MySql全文检索使用详解
实际项目中经常会有一个字段存储多个值用逗号分隔的场景,当分开查询的时候,使用模糊查询会非常影响效率.mysql提供了全文检索函数可以有效解决这一问题: 1.数据结构 ID CODE MSG 1 111 ...
- Sphinx 全文检索
什么是全文检索: 全文检索是指以文档的全部文本信息作为检索对象的一种信息检索技术.检索的对象有可能是文章的标题,也有可能是文章的作者,也有可能是文章摘要或内容. 简介: Sphinx是由俄罗斯人And ...
随机推荐
- 【Android界面实现】使用PagerTabStrip实现有滑动标签的Viewpager
在ViewPager这样的能够滑动的控件上,总是有非常多的文章能够做.上次的文章,我们实现了一个自己定义的ViewPager的指示器,这篇文章,我们主要是想利用Android自带的控件,实现一个指示器 ...
- android中抽屉布局DrawerLayout的使用
这个抽屉布局类似于手机QQ的主界面,点击左上角头像,会从界面左侧弹出一个抽屉,展示一些内容. 首先是布局界面activity_main.xml: <?xml version="1.0& ...
- uni - 自定义组件
目录结构如下 点击下载自定义组件示例
- vue循环中的v-show
v-show如果使用循环对象的属性来时控制, 这个属性必须是加载时就存在的 <div class="list-group col-sm-12" v-for="(is ...
- java byte数组与String互转
java byte数组与String互转 CreationTime--2018年7月6日14点53分 Author:Marydon 1.String-->byte[] 方法:使用String ...
- Android 仿知乎创意广告
代码地址如下:http://www.demodashi.com/demo/14904.html 一.概述 貌似前段时间刷知乎看到的一种非常有特色的广告展现方式,即在列表页,某一个Item显示背后部分广 ...
- 自己使用过比较好用的VSCode插件
C/C++ [ms-vscode.cpptolls] 智能推导,调试和代码浏览 C/C++ Clang Command Adapter [mitaki28.vscode-clang] 使用 ...
- 【mysql】数据库Schema的优化
由于MySQL数据库是基于行(Row)存储的数据库,而数据库操作 IO 的时候是以 page(block)的方式,也就是说,如果我们每条记录所占用的空间量减小,就会使每个page中可存放的数据行数增大 ...
- Guice与Spring框架的区别
2007-4-23 再借斧子的例子说一说spring与guice的区别 看下边对于不同社会形态下一个人(java对象,调用者)需要一把斧子(java对象,被调用者)的例子: (1),原始社会 ...
- Mac终端查看sqlite3数据库、表数据等(含sqlite可视化工具下载)
背景: 有时候,我们在用FMDB等库处理iOS数据库时,沙盒里保存的数据库格式为.sqlite3. 那么,我们如何查看这个数据库呢? 其实有两种方法: 1.借助工具 - Sqlite Database ...