mysql5.6全文索引中文,mysql5.6 InnoDB 全文索引 FULLTEXT 中文解決方案 base64

mysql5.6 innlDB 在CHAR、VARCHAR、TEXT類型的列上可以定義全文索引,但因為無法中文分詞所以對中文的支持很差,但從MySQL5.7開始,MySQL內置了ngram全文檢索插件,用來支持中文分詞,並且對MyISAM和InnoDB引擎有效。

在沒法升級5.7的情況下,5.6有變通的辦法,就是將整句的中文拆分成單個漢字,並按urlencode、區位碼、base64、拼音等進行編碼使之以"字母+數字"的方式存儲於數據庫中。轉換完達到如下的效果:

14118609ab77edc109c5b269228c2669.png

存儲的是將漢字編碼后的結果,用空格連起來,這樣就可以使用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];

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值