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

MySQL 全文搜尋實戰:MATCH AGAINST 語法、中文分詞與 PHP 模擬方案

     編輯:MySQL 資料庫相關知識

原生全文搜尋語法

SELECT * FROM articles
WHERE MATCH (title, body) AGAINST ('database' IN NATURAL LANGUAGE MODE);

-- 顯示相關度分數並排序
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;

關鍵模式

模式特點
NATURAL LANGUAGE MODE預設,計算相關度,需 FULLTEXT 索引,忽略停用詞、短詞(預設 <4 字元)
IN BOOLEAN MODE支援 + - * "" 運算子,不計算相關度,可不走索引
WITH QUERY EXPANSION盲目擴展:先搜尋,再用高相關文檔關鍵詞二次搜尋

限制與注意

  • 僅支援 MyISAM(5.6+ InnoDB 亦支援)。
  • 最小詞長 ft_min_word_len(預設 4),中文單字多為 1-2 字,**原生全文搜尋不適合中文**。
  • 停用詞表 ft_stopword_file 可自訂。
  • 50% 門檻:自然語言模式下,出現在超過 50% 文檔的詞會被忽略。

中文分詞核心難題

MySQL 內建不支援 CJK(中日韓)分詞。解決路徑:應用層分詞 → 建立倒排索引表 → 搜尋時同樣分詞匹配。

PHP 模擬分詞實作(N-gram / Bigram 示例)

function chineseSegment($str, $encoding = 'utf-8') {
    $stopWords = ['的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一個', '上', '也', '很', '到', '說', '要', '去', '你', '會', '著', '看', '好', '自己', '這'];
    
    // 移除 HTML 標籤
    $str = preg_replace('/<[^>]+>/', '', $str);
    // 移除停用詞
    $str = str_replace($stopWords, ' ', $str);
    
    $len = mb_strlen($str, $encoding);
    $terms = [];
    
    for ($i = 0; $i < $len - 1; $i++) {
        $bigram = mb_substr($str, $i, 2, $encoding);
        // 過濾純標點/空白
        if (preg_match('/^[\p{Han}\p{L}\p{N}]{2}$/u', $bigram)) {
            $terms[] = $bigram;
        }
    }
    // 英文/數字單獨提取
    preg_match_all('/[a-zA-Z0-9]+/', $str, $enMatches);
    $terms = array_merge($terms, $enMatches[0]);
    
    return array_unique($terms);
}

// 寫入全文索引表
$terms = chineseSegment($articleTitle . ' ' . $articleBody);
$indexStr = implode(' ', $terms);
$db->query("UPDATE article_ft SET keywords='$indexStr' WHERE article_id=$id");

搜尋時同樣分詞

$qTerms = chineseSegment($userQuery);
$where = '';
foreach ($qTerms as $t) {
    $where .= "keywords LIKE '%$t%' OR ";
}
$where = rtrim($where, ' OR ');
$sql = "SELECT * FROM article_ft WHERE $where";

生產環境建議

  • 資料量 < 100萬:MySQL + 應用層 Bigram 可接受。
  • 資料量 > 100萬或需高精度:引入 Elasticsearch、Sphinx、Meilisearch,支援 IK、Jieba、SmartCN 等專業中文分詞器。
  • 索引表欄位加 FULLTEXT(keywords) 加速 MATCH AGAINST(需 MyISAM 或 5.6+ InnoDB)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved