首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 全文搜尋語法與中文分詞實作方案

     編輯:MySQL 資料庫相關知識

MySQL 原生全文搜尋語法

MATCH (col1, col2, ...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION])

基本範例

-- 自然語言模式
SELECT * FROM articles WHERE MATCH (title, body) AGAINST ('database');

-- 顯示相關度分數並排序
SELECT id, body,
       MATCH (title, body) AGAINST ('Security implications of running MySQL as root') AS score
FROM articles
WHERE MATCH (title, body) AGAINST ('Security implications of running MySQL as root')
ORDER BY score DESC;

全文搜尋限制與注意事項

  • 最小字詞長度:預設 4 個字元,可調整 ft_min_word_len。
  • 停用字:內建停用字表會被忽略,可自訂 ft_stopword_file。
  • 50% 門檻:自然語言模式下,出現在超過 50% 資料列的字詞會被忽略(Boolean 模式不受影響)。
  • 不支援中文分詞:MySQL 內建無 CJK(中日韓)分詞能力。

PHP 模擬中文分詞方案(雙字切分法)

核心邏輯:將中文文字以雙字滑動窗口切分,如「資料庫應用」→「資料」「料庫」「庫應」「應用」。搜尋時同樣切分,達到模糊匹配。

關鍵函數:DV_ChineseWordSegment

function DV_ChineseWordSegment($str, $encodingName='gbk') {
    // 1. 移除 HTML 標籤
    $str = preg_replace('#<[a-zA-Z]+?.*?>|#is', '', $str);
    // 2. 過濾停用字
    $str = str_replace($arrStopWords['StrRepl'], ' ', $str);
    $str = preg_replace($arrStopWords['PregRepl'], ' ', $str);
    // 3. 英文單獨保留,中文雙字切分
    $arr = explode(' ', $str);
    foreach ($arr as $tmpStr) {
        if (preg_match('/^[\x00-\x7f]+$/i', $tmpStr)) {
            $returnVal[] = ' ' . $tmpStr;  // 純英文
        } else {
            // 英文部分單獨提取
            preg_match_all('/([a-zA-Z]+)/i', $tmpStr, $matches);
            if (!empty($matches[0])) {
                foreach ($matches[0] as $matche) $returnVal[] = $matche;
            }
            // 移除 ASCII,剩下中文進行雙字切分
            $tmpStr = preg_replace('/([\x00-\x7f]+)/i', '', $tmpStr);
            $strLen = $objEnc->StrLength($tmpStr) - 1;
            for ($i = 0; $i < $strLen; $i++) {
                $returnVal[] = $objEnc->SubString($tmpStr, $i, 2);  // 雙字切分
            }
        }
    }
    return $returnVal;
}

寫入全文索引表

$arrTopicIndex = DV_ChineseWordSegment($topic);
if (!empty($arrTopicIndex)) {
    $topicindex = $db->escape_string(implode(' ', $arrTopicIndex));
    if ($topicindex !== '') {
        $db->query("UPDATE {$dv}topic_ft SET topicindex='{$topicindex}' WHERE topicid='{$RootID}'");
    } else {
        $db->query("DELETE FROM {$dv}topic_ft WHERE topicid='{$RootID}'");
    }
}

現代替代方案

  • MySQL 5.7.6+ 內建 ngram parser 支援中日韓分詞:CREATE FULLTEXT INDEX idx ON tbl(col) WITH PARSER ngram;
  • Elasticsearch / OpenSearch:專業全文搜尋引擎,支援中文分詞器(ik、jieba)。
  • PostgreSQL:搭配 pg_trgm、zhparser 等擴充套件。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved