-
2021-02-03 21:08:24
对于英文,MySQL的FULLTEXT属性来实现全文检索是相当方便且高效的,但是在使用过程中需要注意一些事项。
首先对我们对需要进行检索的字段添加FULLTEXT属性(假设已经建表):
SQL:
alter table table_name add fulltext index(filed_1,filed_2);
接下来查询数据:
SQL:
SELECT * FROM table_name WHERE MATCH (filed_1,filed_2) AGAINST ('keyword');
此处涉及到一个很重要的注意事项:
MySQL规定全文搜索中被搜索的单词所在的行数大于等于被搜索的所有行数的一半时候,就将被搜索单词作为Common word,即不被显示。(具体条件需要查阅资料确定)
因此,假设在测试的时候,表中只有一行数据,所以无论怎么执行上述查询语句,返回的结果总是为空。不必惊慌,多加几条没有待查关键词的数据就会有结果啦~
当然,MySQL提供了更加强大的查询结果过滤:
SQL:
SELECT * FROM table_name WHERE MATCH (filed_1,filed_2) AGAINST ('+keyword_1 -keyword_2' IN BOOLEAN MODE);
这样,就会返回包含keyword_1的数据,而包含keyword_2的数据就会被过滤掉。
更多相关内容 -
mysql5.6 InnoDB 全文索引 FULLTEXT 中文解决方案 base64
2021-03-03 17:49:52mysql5.6 innlDB在CHAR、VARCHAR、TEXT类型的列上可以定义全文索引,但因为无法中文...在没法升级5.7的情况下,5.6有变通的办法,就是将整句的中文拆分成单个汉字,并按urlencode、区位码、base64、拼音等进行编码...mysql5.6 innlDB 在CHAR、VARCHAR、TEXT类型的列上可以定义全文索引,但因为无法中文分词所以对中文的支持很差,但从MySQL5.7开始,MySQL内置了ngram全文检索插件,用来支持中文分词,并且对MyISAM和InnoDB引擎有效。
在没法升级5.7的情况下,5.6有变通的办法,就是将整句的中文拆分成单个汉字,并按urlencode、区位码、base64、拼音等进行编码使之以"字母+数字"的方式存储于数据库中。转换完达到如下的效果:
存储的是将汉字编码后的结果,用空格连起来,这样就可以使用5.6的全文索引来进行搜索,注意的是要将搜索的内容也先同样编码再进行搜索。
下面给出一种基于base64的汉字变换方式
/**
* 关键词整理函数(用作mysql的全文索引制作的搜索)
* 1.将字符串全角转半角、去空格、大写转小写、分成单个字符并base64编码、最后用空格连接类,方便mysql索引,做搜索关键字
* 2.将数字转全角做索引区分标识,全角数字为标识专用
**/
function keywords($str){//全角转半角
$str = strtr($str,['1' => '1','2' => '2','3' => '3','4' => '4','5' => '5','6' => '6','7' => '7','8' => '8','9' => '9','0' => '0',
'A' => 'A','B' => 'B','C' => 'C','D' => 'D','E' => 'E','F' => 'F','G' => 'G','H' => 'H','I' => 'I','J' => 'J','K' => 'K','L' => 'L','M' => 'M','N' => 'N','O' => 'O','P' => 'P','Q' => 'Q','R' => 'R','S' => 'S','T' => 'T','U' => 'U','V' => 'V','W' => 'W','X' => 'X','Y' => 'Y','Z' => 'Z',
'a' => 'a','b' => 'b','c' => 'c','d' => 'd','e' => 'e','f' => 'f','g' => 'g','h' => 'h','i' => 'i','j' => 'j','k' => 'k','l' => 'l','m' => 'm','n' => 'n','o' => 'o','p' => 'p','q' => 'q','r' => 'r','s' => 's','t' => 't','u' => 'u','v' => 'v','w' => 'w','x' => 'x','y' => 'y','z' => 'z',
'~' => '~','`' => '`','!' => '!','@' => '@','#' => '#','$' => '$','%' => '%','^' => '^','&' => '&','*' => '*','(' => '(',')' => ')','_' => '_','-' => '-','+' => '+','=' => '=',
'{' => '{','}' => '}','[' => '[',']' => ']','|' => '|','\' => '\\',':' => ':',';' => ';','"' => '"',''' => '\'',
'<' => ' ',','>' => '>','.' => '.','?' => '?','/' => '/',' ' => ' ']);//去空格
$str = str_replace(' ','',$str);//大写转小写
$str = strtolower($str);//数字统一格式为阿拉伯数字
$str = strtr($str,['零' => 0,'一' => 1,'二' => 2,'三' => 3,'四' => 4,'五' => 5,'六' => 6,'七' => 7,'八' => 8,'九' => 9]);//分成单个字符并base64编码
$str_len = strlen($str);//获取关键字集合
$arr =[];$str_len = mb_strlen($str);for($i = 0;$i < $str_len;++ $i){$keyword = strtr(base64_encode(mb_substr($str,$i,1)),'+/=','abc');if(!in_array($keyword,$arr)){ //去除重复的关键字
$arr[] = $keyword;
}
}return $arr;
}
例如将字符串 '小明小红是朋友' 输入改函数,返回的结果是数组如下
array(6) {
[0]=>
string(4) "5bCP"[1]=>
string(4) "5piO"[2]=>
string(4) "57qi"[3]=>
string(4) "5piv"[4]=>
string(4) "5pyL"[5]=>
string(4) "5YaL"}
分别对应相应的汉字,注意小明和小红都有小这个字,所以去掉重复的字,只有六个编码。
然后用空格将数组连起来
$keywords = implode(' ',keywords($keyword));
将$keywords 存入数据库。
进阶:
如果匹配的关键词包含一些常用的字,会出现大量的结果。
例如搜索书名 霸道总裁,可能会出现,裁缝,总经理,这样的结果
全文搜索是按照相关度从高到底返回的结果,可以只去去前面一些相关度较高的结果。
或者先查询出相关度最高是多少(相关度是一个数值),然后除以二,限定结果的相关度都大于这个最大相关度的一半。
参考
//通过最大相关度/2过滤一部分无关结果//查询出最大相关度是多少
$score = $this->sql('xs.nh')->query('SELECT MATCH(keywords_base) AGAINST (?) AS score FROM nh ORDER BY score DESC LIMIT 1',[$keywords]);//构造查询语句
$this->where['MATCH(keywords_base) AGAINST'] = [$keywords,'> '.$score[0]['score'] / 2];
-
MySQL fulltext index检索中文注意事项
2021-01-30 00:00:52Empty set (0.00 sec) 经查询,ngram_token_size=2 #用中文检索分词插件ngram之前,先得在MySQL配置文件里面设置他的分词大小 7、更改参数 ngram_token_size=1,并重启实例 mysql> show variables like 'ng%...1、查看表结构
mysql> show create table product_test02;
| Table | Create Table
| product_test02 | CREATE TABLE `product_test02` (
`product_id` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`artisan_id` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`name` varchar(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`des` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
`zhima_price` double(11,2) DEFAULT NULL,
`market_price` double(11,2) DEFAULT NULL,
`cover_pic` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`work_time` int(11) DEFAULT NULL,
`comment_count` int(11) DEFAULT NULL,
`like_count` int(11) DEFAULT NULL,
`produt_consist` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`keep_time` int(11) DEFAULT NULL,
`create_at` timestamp NULL DEFAULT NULL,
`fav_count` int(11) DEFAULT NULL,
`width` int(11) DEFAULT NULL,
`height` int(11) DEFAULT NULL,
`is_publish` int(11) DEFAULT NULL,
`is_top` int(11) DEFAULT NULL,
`is_delete` int(11) DEFAULT NULL,
`sell_amount` int(11) DEFAULT '0',
`free_service_time` int(11) DEFAULT NULL,
`update_time` timestamp NULL DEFAULT NULL,
`other_1` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`other_2` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`other_3` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`other_4` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`other_5` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`is_audit` tinyint(1) DEFAULT '0',
`audit_time` timestamp NULL DEFAULT NULL,
`is_undercarriage` tinyint(1) DEFAULT '0',
`undercarriage_time` timestamp NULL DEFAULT NULL,
`category` varchar(30) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`active_tag_dict_id` bigint(20) DEFAULT NULL,
`active_price` double(11,1) DEFAULT NULL,
`weight` int(11) unsigned DEFAULT '0',
`fit_people` varchar(300) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`matter_attent` varchar(800) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`category_lv2_id` int(11) DEFAULT NULL,
`artisan_visit` int(1) DEFAULT '1',
`customer_visit` int(1) DEFAULT '0',
`customer_zhima_price` double(11,2) DEFAULT NULL,
`customer_market_price` double(11,2) DEFAULT NULL,
`service_sex` int(1) DEFAULT '0',
`service_mode` tinyint(2) DEFAULT '0' ,
`last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`sell_price` double(11,2) NOT NULL DEFAULT '0.00',
`is_new` int(1) NOT NULL,
`spu_id` int(11) DEFAULT NULL,
`category_id` int(11) DEFAULT NULL,
`other_info` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`product_type` int(2) NOT NULL DEFAULT '0' ,
`product_code` varchar(15) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2、在name字段创建fulltext索引
mysql> alter table product_test02 add FULLTEXT index ft_indx_name (name) WITH PARSER ngram;
Query OK, 0 rows affected, 1 warning (3 min 45.93 sec)
3、利用fulltext index进行检索
mysql> select name from product_test02 where match(name) against ('头部' in boolean mode) limit 1;
+---------------------+
| name |
+---------------------+
| 头部按*摩+拨筋 |
+---------------------+
1 row in set (0.00 sec)
mysql> select name from product_test02 where match(name) against ('头' in boolean mode) limit 1;
Empty set (0.00 sec)
经查询:这个是数据库ft_min_word_len参数有关,默认为4,至少检索4个字符,被检索字符串长度小于4个字符将检索不到。
4、
改参数
ft_min_word_len = 1并重启实例
mysql> show variables like 'ft%';
+--------------------------+----------------+
| Variable_name | Value |
+--------------------------+----------------+
| ft_boolean_syntax | + ->
| ft_max_word_len | 84 |
| ft_min_word_len | 1 |
| ft_query_expansion_limit | 20 |
| ft_stopword_file | (built-in) |
+--------------------------+----------------+
5、再次查询
mysql> select name from product_test02 where match(name) against ('头' in boolean mode) limit 1;
Empty set (0.01 sec)
依然查询不到,原因是
ft_min_word_len 参数改完之后,必须重建所有fulltext index
6、重建fulltext index并检索
mysql> select name from product_test02 where match(name) against ('头部' in boolean mode) limit 1;
Empty set (0.00 sec)
mysql> select name from product_test02 where match(name) against ('3' in boolean mode) limit 1;
Empty set (0.00 sec)
经查询,ngram_token_size=2 #用中文检索分词插件ngram之前,先得在MySQL配置文件里面设置他的分词大小
7、更改参数
ngram_token_size=1,并重启实例
mysql> show variables like 'ng%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| ngram_token_size | 1 |
+------------------+-------+
1 row in set (0.01 sec)
mysql> select name from product_test02 where match(name) against ('头部' in boolean mode) limit 1;
+---------------------------------------------+
| name |
+---------------------------------------------+
| 【头疼必拍】头部舒压+经络疏通 |
+---------------------------------------------+
1 row in set (0.01 sec)
mysql> select name from product_test02 where match(name) against ('头' in boolean mode) limit 1;
+--------------------------------------------------+
| name |
+--------------------------------------------------+
| 头部拨筋头晕头痛失眠【头部调理】 |
+--------------------------------------------------+
1 row in set (0.01 sec)
可以正常检索。
-
mysql5.6 InnoDB 全文索引 FULLTEXT 中文解決方案 base64
2021-04-20 08:45:55mysql5.6 innlDB在CHAR、VARCHAR、TEXT類型的列上可以定義全文索引,但因為無法中文分詞所以對中文的支持很差,但從MySQL5.7開始,MySQL內置了ngram全文檢索插件,用來支持中文分詞,並且對MyISAM和InnoDB引擎有效。...mysql5.6 innlDB 在CHAR、VARCHAR、TEXT類型的列上可以定義全文索引,但因為無法中文分詞所以對中文的支持很差,但從MySQL5.7開始,MySQL內置了ngram全文檢索插件,用來支持中文分詞,並且對MyISAM和InnoDB引擎有效。
在沒法升級5.7的情況下,5.6有變通的辦法,就是將整句的中文拆分成單個漢字,並按urlencode、區位碼、base64、拼音等進行編碼使之以"字母+數字"的方式存儲於數據庫中。轉換完達到如下的效果:
存儲的是將漢字編碼后的結果,用空格連起來,這樣就可以使用5.6的全文索引來進行搜索,注意的是要將搜索的內容也先同樣編碼再進行搜索。
下面給出一種基於base64的漢字變換方式
/**
* 關鍵詞整理函數(用作mysql的全文索引制作的搜索)
* 1.將字符串全角轉半角、去空格、大寫轉小寫、分成單個字符並base64編碼、最后用空格連接類,方便mysql索引,做搜索關鍵字
* 2.將數字轉全角做索引區分標識,全角數字為標識專用
**/
function keywords($str){//全角轉半角
$str = strtr($str,['1' => '1','2' => '2','3' => '3','4' => '4','5' => '5','6' => '6','7' => '7','8' => '8','9' => '9','0' => '0',
'A' => 'A','B' => 'B','C' => 'C','D' => 'D','E' => 'E','F' => 'F','G' => 'G','H' => 'H','I' => 'I','J' => 'J','K' => 'K','L' => 'L','M' => 'M','N' => 'N','O' => 'O','P' => 'P','Q' => 'Q','R' => 'R','S' => 'S','T' => 'T','U' => 'U','V' => 'V','W' => 'W','X' => 'X','Y' => 'Y','Z' => 'Z',
'a' => 'a','b' => 'b','c' => 'c','d' => 'd','e' => 'e','f' => 'f','g' => 'g','h' => 'h','i' => 'i','j' => 'j','k' => 'k','l' => 'l','m' => 'm','n' => 'n','o' => 'o','p' => 'p','q' => 'q','r' => 'r','s' => 's','t' => 't','u' => 'u','v' => 'v','w' => 'w','x' => 'x','y' => 'y','z' => 'z',
'~' => '~','`' => '`','!' => '!','@' => '@','#' => '#','$' => '$','%' => '%','^' => '^','&' => '&','*' => '*','(' => '(',')' => ')','_' => '_','-' => '-','+' => '+','=' => '=',
'{' => '{','}' => '}','[' => '[',']' => ']','|' => '|','\' => '\\',':' => ':',';' => ';','"' => '"',''' => '\'',
'<' => ' ',','>' => '>','.' => '.','?' => '?','/' => '/',' ' => ' ']);//去空格
$str = str_replace(' ','',$str);//大寫轉小寫
$str = strtolower($str);//數字統一格式為阿拉伯數字
$str = strtr($str,['零' => 0,'一' => 1,'二' => 2,'三' => 3,'四' => 4,'五' => 5,'六' => 6,'七' => 7,'八' => 8,'九' => 9]);//分成單個字符並base64編碼
$str_len = strlen($str);//獲取關鍵字集合
$arr =[];$str_len = mb_strlen($str);for($i = 0;$i < $str_len;++ $i){$keyword = strtr(base64_encode(mb_substr($str,$i,1)),'+/=','abc');if(!in_array($keyword,$arr)){ //去除重復的關鍵字
$arr[] = $keyword;
}
}return $arr;
}
例如將字符串 '小明小紅是朋友' 輸入改函數,返回的結果是數組如下
array(6) {
[0]=>
string(4) "5bCP"[1]=>
string(4) "5piO"[2]=>
string(4) "57qi"[3]=>
string(4) "5piv"[4]=>
string(4) "5pyL"[5]=>
string(4) "5YaL"}
分別對應相應的漢字,注意小明和小紅都有小這個字,所以去掉重復的字,只有六個編碼。
然后用空格將數組連起來
$keywords = implode(' ',keywords($keyword));
將$keywords 存入數據庫。
進階:
如果匹配的關鍵詞包含一些常用的字,會出現大量的結果。
例如搜索書名 霸道總裁,可能會出現,裁縫,總經理,這樣的結果
全文搜索是按照相關度從高到底返回的結果,可以只去去前面一些相關度較高的結果。
或者先查詢出相關度最高是多少(相關度是一個數值),然后除以二,限定結果的相關度都大於這個最大相關度的一半。
參考
//通過最大相關度/2過濾一部分無關結果//查詢出最大相關度是多少
$score = $this->sql('xs.nh')->query('SELECT MATCH(keywords_base) AGAINST (?) AS score FROM nh ORDER BY score DESC LIMIT 1',[$keywords]);//構造查詢語句
$this->where['MATCH(keywords_base) AGAINST'] = [$keywords,'> '.$score[0]['score'] / 2];
-
MySQL使用全文索引(fulltext index) 及中文全文索引使用
2022-05-07 16:50:03创建全文索引(FullText index) 旧版的MySQL的全文索引只能用在MyISAM表格的char、varchar和text的字段上。 不过新版的MySQL5.6.24上InnoDB引擎也加入了全文索引,所以具体信息要随时关注官网, 1.1. 创建表的同时... -
MySQL中的FULLTEXT搜索不返回任何行
2021-01-27 14:31:45Query OK, 0 rows affected (0.02 sec) mysql> ALTER TABLE articles ADD FULLTEXT(body, title); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> insert into articles(body)... -
InnoDB FULLTEXT
2021-02-04 19:01:211.概要InnoDB引擎对FULLTEXT索引的支持是MySQL5.6新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引。对于FULLTEXT索引的内容可以使用MATCH()…AGAINST语法进行...比如,为了监视一个FULLTEXT索引中文本处理过程... -
mysql fulltext 没有结果_MySql 全文检索两个字符的内容无法得到结果
2021-04-07 17:06:29innodb_ft_user_stopword_table | | +---------------------------------+----------------+ FULLTEXT索引是按照“词”进行的索引,MySQL默认的分词方法是所有非字母和数字的特殊符号都是分词符(如果希望对中文进行... -
MySQL(FullText)
2021-01-18 20:48:34fulltext变量:show variables like "%FT%"+---------------------------------+----------------+| ft_boolean_syntax | + ->| ft_max_word_len | 84 || ft_min_word_le... -
MySQL FULLTEXT不工作
2021-01-27 14:31:15我正在尝试使用MySQL的FULLTEXT索引添加对我的PHP Web应用程序的搜索支持。我创建了一个测试表(使用MyISAM类型,单个文本字段a)并输入了一些示例数据。现在如果我是正确的,以下查询应该返回这两行:SELECT * FROM ... -
mysql fulltext
2020-06-04 16:58:34首页要先明白mysql的全文检索原理:mysql使用的是一个非常简单的剖析器来将文本分隔成词,空格、标点等,比如‘welcom to you’将分隔为三个词‘welcom’、‘to’、‘you’,但是对中文来说,比如‘人力方网站正式... -
MySQL 之全文索引(fulltext)
2021-08-27 09:37:09最近在复习数据库索引部分,看到了 fulltext,也即全文索引,虽然全文索引在平时的业务中用到的不多,但是感觉它有点儿意思,所以花了点时间研究一下,特此记录。 引入 概念 通过数值比较、范围过滤等就可以完成绝... -
在mysql中使用全文索引fulltext|mysql,全文索引,fulltext
2021-01-21 03:32:56全文检索在 MySQL 中就是一个 FULLTEXT 类型索引。FULLTEXT 索引用于 MyISAM 表,可以在 CREATE TABLE 时或之后使用 ALTER TABLE 或 CREATE INDEX 在 CHAR、 VARCHAR 或 TEXT 列上创建。对于大的数据库,将数据装载... -
mysql全文索引FULLTEXT
2019-07-22 11:34:50innodb支持全文索引 之前的旧版的MySQL的全文索引只能用在MyISAM表格的char、varchar和text的字段上。 后来新版的MySQL5.6.24上InnoDB引擎也加入了全文索引,所以具体信息...这对于像中文的语言是没发进行分... -
mysql深入理解全文索引fulltext及实例剖析
2021-01-20 14:37:43本文章通过以下几个小章节向大家介绍mysql全文索引的相关知识:mysql全文索引原理及使用条件如何创建...空格、标点等,比如‘welcom to you’将分隔为三个词‘welcom’、‘to’、‘you’,但是对中文来说,比如‘... -
MySQL全文索引 FULLTEXT索引和like的区别
2021-01-19 09:21:471.概要InnoDB引擎对FULLTEXT索引的支持是MySQL5.6新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引。对于FULLTEXT索引的内容可以使用MATCH()…AGAINST语法进行...比如,为了监视一个FULLTEXT索引中文本处理过程... -
MySQL 中文分词原理
2021-01-18 23:56:58然后用编码工具把每个中文词语编译成英文字符乱码,接着,每个英文乱码之间也用空格间隔,这样就成功的把一篇中文翻译成看不懂的英文文章了,我们就可以使用fulltext索引,在这篇看不懂的英文文章中进行全文本搜素。... -
fulltext
2022-06-10 17:13:12Fulltext 2022-04-10 18:14:07 +0800 false 全文索引 原本是想利用全文索引解决简单的查询优化,但使用了之后发现一些问题。 配置问题 全文索引都会涉及到一个最小分词长度长度的配置; #在mysql查询配置 ... -
[MySQL] 原生全文检索 fulltext 的简单应用
2021-03-03 18:21:17在目标字段上添加全文检索:alter table 表名 add fulltext(字段) with parser ngram查询语句:select * from xxx where match(字段)against ('检索词' in natural language mode)查看词的权重:SELECT content,... -
MySQL 全文检索方案 - FULLTEXT 索引
2021-01-18 20:46:27实际上,就是增加了一个新的索引类型 FULLTEXT FULLTEXT 索引只能用于 InnoDB 及 MyISAM 表,可以应用于 CHAR,VARCHAR,TEXT 字段 提供了内置的支持 CJK (中文,日文,韩文)的 ngram 分词器 对于大量数据,先插... -
mysql fulltext索引
2020-06-04 16:41:51首页要先明白mysql的全文检索原理:mysql使用的是一个非常简单的剖析器来将文本分隔成词,空格、标点等,比如‘welcom to you’将分隔为三个词‘welcom’、‘to’、‘you’,但是对中文来说,比如‘人力方网站正式...