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

Sphinx 搜索子域名匹配實戰:charset_table 配置、分隔符處理與特殊字符轉義

     編輯:MySQL 資料庫相關知識

使用 Sphinx 實現子域名匹配(搜 jb51.net 命中 www.jb51.net、host.jb51.net)時,默認分詞器以點號 . 為分隔符,導致過度分詞(命中 jb51.a.cn)與漏匹配(漏掉 jb51.net.com)。本文通過 charset_table 配置、邊界後綴標記、特殊字符替換三步徹底解決域名搜索精準匹配問題。

問題現場

  • 搜索 jb51.net → 分詞為 jb51、net → 命中 aajb51.net、jb51.a.cn、jb51.net.com(噪音極大)。
  • 期望:僅命中以 jb51.net 結尾的域名(含子域名)。

三步解決方案

步驟 1:charset_table 納入點號,禁止分詞分割

在 sphinx.conf index 區塊配置:

charset_table = 0..9, A..Z->a..z, a..z, U+002E, U+002D, U+0040, U+0060
# 含義:
# 0-9 數字
# A-Z 大寫轉小寫 + a-z 小寫
# U+002E = '.' (點號)  ← 關鍵:將點號視為字符而非分隔符
# U+002D = '-' (連字符)
# U+0040 = '@' 
# U+0060 = '`' (反引號,備用特殊字符)

效果:jb51.net 作為整體詞項進入索引,不再拆分為 jb51 + net。解決 jb51.a.cn 類誤命中。

步驟 2:索引構建時添加唯一後綴,精確邊界匹配

數據源 SQL 中對域名字段拼接唯一標記(如 __END__):

sql_query = SELECT id, CONCAT(domain, '__END__') AS domain_idx FROM domains;

搜索時同樣帶上後綴:

SELECT * FROM domains_idx WHERE MATCH('jb51.net__END__');

效果:精確匹配以 jb51.net 結尾的域名,排除 jb51.net.com(其索引為 jb51.net.com__END__,不匹配)。

步驟 3:特殊字符替換方案,解決引號/點號語法衝突

SphinxQL 中 MATCH('@"jb51.net"')(雙引號短語匹配)與點號、單引號存在解析衝突。實測最穩健方案:

  1. 將查詢中的點號 . 替換為反引號 `(已在 charset_table 納入)。
  2. 搜索語句:MATCH('`jb51`net__END__')(或直接用步驟 2 的後綴法,無需短語匹配)。

替換規則表:

原字符替換為Unicodecharset_table 需包含
.`U+0060U+0060
--U+002DU+002D
@@U+0040U+0040

完整配置示例

source domains_src
{
    type = mysql
    sql_host = localhost
    sql_user = sphinx
    sql_pass = secret
    sql_db = mydb
    sql_query = SELECT id, CONCAT(domain, '__END__') AS domain_idx FROM domains
    sql_attr_uint = id
}

index domains_idx
{
    source = domains_src
    path = /var/lib/sphinx/domains_idx
    charset_table = 0..9, A..Z->a..z, a..z, U+002E, U+002D, U+0040, U+0060
    min_word_len = 1
    enable_star = 1  # 支持通配符 *
}

searchd
{
    listen = 9306:mysql41
    log = /var/log/sphinx/searchd.log
    query_log = /var/log/sphinx/query.log
}

搜索驗證

-- 命中 www.jb51.net、jb51.net、host.jb51.net
SELECT * FROM domains_idx WHERE MATCH('jb51.net__END__');

-- 不命中 jb51.net.com、aajb51.net
SELECT * FROM domains_idx WHERE MATCH('jb51.net.com__END__');

避坑清單

  • charset_table 修改後必須重建索引:indexer --rotate domains_idx。
  • 替換字符必須在 charset_table 中,否則被忽略導致匹配失效。
  • 短語匹配雙引號語法極不穩定,生產環境堅持後綴標記法(__END__)。
  • 中文域名/IDN:需在 charset_table 納入 CJK 範圍或使用 ngram_chars,另行規劃。

總結

Sphinx 子域名精準匹配三板斧:
1. charset_table 納入點號 → 禁止過度分詞。
2. 索引/查詢雙端加唯一後綴 → 精確邊界匹配,排除父域名干擾。
3. 特殊字符統一替換為反引號 → 規避解析器衝突。
配置生效後重建索引,即可實現「搜主域名,命中所有子域名,排除無關域名」的業務語義。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved