天天看點

Sphinx中文指南

  • 1、簡介
  • 1.1.Sphinx是什麼
  • 1.2.Sphinx的特性
  • 1.3.Sphinx中文分詞
  • 2、安裝配置執行個體
  • 2.1 在GNU/Linux/unix系統上安裝
  • 2.1.1 sphinx安裝
  • 2.1.2.sfc安裝(見另文)
  • 2.1.3.coreseek安裝(見另文)
  • 2.2 在windows下安裝
  • 3、 配置執行個體
  • 4、應用
  • 4.1 在CLI上測試
  • 4.2 使用API調用
  • 5、附錄

1.Sphinx簡介

1.1.Sphinx是什麼

Sphinx是由俄羅斯人Andrew Aksyonoff開發的一個全文檢索引擎。意圖為其他應用提供高速、低空間占用、高結果 相關度的全文搜尋功能。Sphinx可以非常容易的與SQL資料庫和腳本語言內建。目前系統内置MySQL和PostgreSQL 資料庫資料源的支援,也支援從标準輸入讀取特定格式 的XML資料。通過修改源代碼,使用者可以自行增加新的資料源(例如:其他類型的DBMS 的原生支援)

1.2.Sphinx的特性

  • 高速的建立索引(在當代CPU上,峰值性能可達到10 MB/秒);
  • 高性能的搜尋(在2 – 4GB 的文本資料上,平均每次檢索響應時間小于0.1秒);
  • 可處理海量資料(目前已知可以處理超過100 GB的文本資料, 在單一CPU的系統上可 處理100 M 文檔);
  • 提供了優秀的相關度算法,基于短語相似度和統計(BM25)的複合Ranking方法;
  • 支援分布式搜尋;
  • 支援短語搜尋
  • 提供文檔摘要生成
  • 可作為MySQL的存儲引擎提供搜尋服務;
  • 支援布爾、短語、詞語相似度等多種檢索模式;
  • 文檔支援多個全文檢索字段(最大不超過32個);
  • 文檔支援多個額外的屬性資訊(例如:分組資訊,時間戳等);
  • 支援斷詞;

1.3.Sphinx中文分詞

中文的全文檢索和英文等latin系列不一樣,後者是根據空格等特殊字元來斷詞,而中文是根據語義來分詞。目前大多數資料庫尚未支援中文全文檢索,如Mysql。故,國内出現了一些Mysql的中文全文檢索的插件,做的比較好的有hightman的中文分詞。Sphinx如果需要對中文進行全文檢索,也得需要一些插件來補充。其中我知道的插件有 ​​coreseek​​​ 和​​ sfc​​ 。

  • Coreseek是現在用的最多的sphinx中文全文檢索,它提供了為Sphinx設計的中文分詞包LibMMSeg。并提供了多個系統的二進制發行版,其中有rpm,deb及windows下的二進制包。另外,coreseek也為sphinx貢獻了以下事項:
  • GBK編碼的資料源支援
  • 采用Chih-Hao Tsai MMSEG算法的中文分詞器
  • 中文​​使用手冊​​(這份中文手冊對國内使用sphinx新手——特别是英語不太好的人來說,提供了極大的便利)
  • sfc(sphinx-for-chinese)是由網友happy兄提供的另外一個中文分詞插件。其中文詞典采用的是xdict。據其介紹,經過測試,目前版本在索引速度上(Linux 測試平台)基本上能夠達到索引UTF-8英文的一半,即官方宣稱速度的一半。(時間主要是消耗在分詞上)。現提供了與sphinx最新版(sphinx 0.9.10)同步的​​sphinx-for-chinese-0.9.10-dev-r2006.tar.gz​​​ 。此版本增加了sql_attr_string,經過本人的測試。其安裝和配置都非常友善。happy兄在分詞方面還有另外一個貢獻——​​php-mmseg​​,這是php對中文分詞的一個擴充庫。

在此,對以上二位作者謹以最大的敬意

  • 此外,如果你對中文分詞不感興趣。或者說僅需要實作類似sql中like的功能,如: select * from product where prodName like ‘%手機%’。sphinx也不會讓你失望,這個或許就是官網對中文的簡單實作——直接對字索引。并且搜尋速度還不錯^_^ 。

本文會對以上三種中文應用進行測試,并以文檔的方式記錄下來,這也許正是本文檔的重點。

2.安裝配置執行個體

2.1在GNU/Linux/unix系統上安裝

Sphinx在mysql上的應用有兩種方式:

①、采用API調用,如使用PHP、java等的API函數或方法查詢。優點是可不必對mysql重新編譯,服務端程序“低耦合”,且程式可靈活、友善的調用;

缺點是如已有搜尋程式的條件下,需修改部分程式。推薦程式員使用。

②、使用插件方式(sphinxSE)把sphinx編譯成一個mysql插件并使用特定的sql語句進行檢索。其特點是,在sql端友善組合,且能直接傳回資料給用戶端

不必二次查詢(注),在程式上僅需要修改對應的sql,但這對使用架構開發的程式很不友善,比如使用了ORM。另外還需要對mysql進行重新編譯,且需要mysql-5.1以上版本

支援插件存儲。系統管理者可使用這種方式

二次查詢注:到現在釋出版本為止——sphinx-0.9.9,sphinx在檢索到結果後隻能傳回記錄的ID,而非要查的sql資料,故需要重新根據這些ID再次從資料庫中查詢,

正在開發的sphinx 0.9.10版本已可存儲這些文本資料,作者曾試過,性能和存儲上的效果都不佳,畢竟還沒出正式版

本文采用的是第一種方式

在*nix系統下安裝,首先需要以下一些軟體支援

軟體環境:
• 作業系統:Centos-5.2
• 資料庫:mysql-5.0.77-3.el5 mysql-devel(如果要使用sphinxSE插件存儲請使用mysql-5.1以上版本)
• 編譯軟體:gcc gcc-c++ autoconf automake
• Sphinx :​​Sphinx-0.9.9​​ (最新穩定版 )
安裝:
• [root@localhost ~]# yum install -y mysql mysql-devel
• [root@localhost ~]# yum install -y automake autoconf
• [root@localhost ~]# cd /usr/local/src/
• [root@localhost src]# wget http://www.sphinxsearch.com/downloads/sphinx-0.9.9.tar.gz
• [root@localhost src]# tar zxvf sphinx-0.9.9.tar.gz
• [root@localhost local]# cd sphinx-0.9.9
• [root@localhost sphinx-0.9.9]# ./configure –prefix=/usr/local/sphinx #注意:這裡sphinx已經預設支援了mysql
• [root@localhost sphinx-0.9.9]# make && make install # 其中的“警告”可以忽略
安裝完畢後檢視一下/usr/local/sphinx下是否有 三個目錄 bin etc var,如有,則安裝無誤!
2.1.2.sfc安裝(點選進入)
2.1.3.coreseek安裝(點選進入)3.配置執行個體
3.1、資料源。
這裡我們采用 mysql的資料源。具體情況如下:
Mysql server:192.168.1.10
Mysql db :test
Mysql 表:test.sphinx_article
mysql> desc sphinx_article;
+———–+———————+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+———–+———————+——+—–+———+—————-+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | | |
| cat_id | tinyint(3) unsigned | NO | MUL | | |
| member_id | int(11) unsigned | NO | MUL | | |
| content | longtext | NO | | | |
| created | int(11) | NO | MUL | | |
+———–+———————+——+—–+———+—————-+
6 rows in set (0.00 sec)3.2、配置檔案
• [root@localhost ~]#cd /usr/local/sphinx/etc #進入sphinx的配置檔案目錄
• [root@localhost etc]# cp sphinx.conf.dist sphinx.conf #建立Sphinx配置檔案
• [root@localhost etc]# vim sphinx.conf #編輯sphinx.conf
具體執行個體配置檔案:
##### 索引源 ###########
source article_src
{
type = mysql    #####資料源類型
sql_host = 192.168.1.10    ######mysql主機
sql_user = root   ########mysql使用者名
sql_pass = pwd############mysql密碼
sql_db = test #########mysql資料庫名
sql_port= 3306 ###########mysql端口
sql_query_pre = SET NAMES UTF8 ###mysql檢索編碼,特别要注意這點,很多人中文檢索不到是資料庫的編碼是GBK或其他非UTF8
sql_query = SELECT id,title,cat_id,member_id,content,created FROM sphinx_article ####### 擷取資料的sql#####以下是用來過濾或條件查詢的屬性############
sql_attr_uint = cat_id ######## 無符号整數屬性
sql_attr_uint = member_id
sql_attr_timestamp = created ############ UNIX時間戳屬性sql_query_info = select * from sphinx_article where id=$id ######### 用于指令界面端(CLI)調用的測試
}
### 索引 ###
index article
{
source = article_src ####聲明索引源
path = /usr/local/sphinx/var/data/article #######索引檔案存放路徑及索引的檔案名
docinfo = extern ##### 文檔資訊存儲方式
mlock = 0 ###緩存資料記憶體鎖定
morphology = none #### 形态學(對中文無效)
min_word_len = 1 #### 索引的詞最小長度
charset_type = utf-8 #####資料編碼##### 字元表,注意:如使用這種方式,則sphinx會對中文進行單字切分,
##### 即進行字索引,若要使用中文分詞,必須使用其他分詞插件如 coreseek,sfccharset_table = U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z,\
A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6,\
U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101,\
U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109,\
U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F,\
U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, \
U+0116->U+0117,U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D,\
U+011D,U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, \
U+0134->U+0135,U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, \
U+013C,U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, \
U+0143->U+0144,U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, \
U+014B,U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, \
U+0152->U+0153,U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159,\
U+0159,U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, \
U+0160->U+0161,U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, \
U+0167,U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, \
U+016E->U+016F,U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175,\
U+0175,U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, \
U+017B->U+017C,U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, \
U+0430..U+044F,U+05D0..U+05EA, U+0531..U+0556->U+0561..U+0586, U+0561..U+0587, \
U+0621..U+063A, U+01B9,U+01BF, U+0640..U+064A, U+0660..U+0669, U+066E, U+066F, \
U+0671..U+06D3, U+06F0..U+06FF,U+0904..U+0939, U+0958..U+095F, U+0960..U+0963, \
U+0966..U+096F, U+097B..U+097F,U+0985..U+09B9, U+09CE, U+09DC..U+09E3, U+09E6..U+09EF, \
U+0A05..U+0A39, U+0A59..U+0A5E,U+0A66..U+0A6F, U+0A85..U+0AB9, U+0AE0..U+0AE3, \
U+0AE6..U+0AEF, U+0B05..U+0B39,U+0B5C..U+0B61, U+0B66..U+0B6F, U+0B71, U+0B85..U+0BB9, \
U+0BE6..U+0BF2, U+0C05..U+0C39,U+0C66..U+0C6F, U+0C85..U+0CB9, U+0CDE..U+0CE3, \
U+0CE6..U+0CEF, U+0D05..U+0D39, U+0D60,U+0D61, U+0D66..U+0D6F, U+0D85..U+0DC6, \
U+1900..U+1938, U+1946..U+194F, U+A800..U+A805,U+A807..U+A822, U+0386->U+03B1, \
U+03AC->U+03B1, U+0388->U+03B5, U+03AD->U+03B5,U+0389->U+03B7, U+03AE->U+03B7, \
U+038A->U+03B9, U+0390->U+03B9, U+03AA->U+03B9,U+03AF->U+03B9, U+03CA->U+03B9, \
U+038C->U+03BF, U+03CC->U+03BF, U+038E->U+03C5,U+03AB->U+03C5, U+03B0->U+03C5, \
U+03CB->U+03C5, U+03CD->U+03C5, U+038F->U+03C9,U+03CE->U+03C9, U+03C2->U+03C3, \
U+0391..U+03A1->U+03B1..U+03C1,U+03A3..U+03A9->U+03C3..U+03C9, U+03B1..U+03C1, \
U+03C3..U+03C9, U+0E01..U+0E2E,U+0E30..U+0E3A, U+0E40..U+0E45, U+0E47, U+0E50..U+0E59, \
U+A000..U+A48F, U+4E00..U+9FBF,U+3400..U+4DBF, U+20000..U+2A6DF, U+F900..U+FAFF, \
U+2F800..U+2FA1F, U+2E80..U+2EFF,U+2F00..U+2FDF, U+3100..U+312F, U+31A0..U+31BF, \
U+3040..U+309F, U+30A0..U+30FF,U+31F0..U+31FF, U+AC00..U+D7AF, U+1100..U+11FF, \
U+3130..U+318F, U+A000..U+A48F,U+A490..U+A4CF
min_prefix_len = 0 #最小字首
min_infix_len = 1 #最小中綴
ngram_len = 1 # 對于非字母型資料的長度切割#加上這個選項,則會對每個中文,英文字詞進行分割,速度會慢
#ngram_chars = U+4E00..U+9FBF, U+3400..U+4DBF, U+20000..U+2A6DF, U+F900..U+FAFF,\
#U+2F800..U+2FA1F, U+2E80..U+2EFF, U+2F00..U+2FDF, U+3100..U+312F, U+31A0..U+31BF,\
#U+3040..U+309F, U+30A0..U+30FF, U+31F0..U+31FF, U+AC00..U+D7AF, U+1100..U+11FF,\
#U+3130..U+318F, U+A000..U+A48F, U+A490..U+A4CF}
######### 索引器配置 #####
indexer
{
mem_limit = 256M ####### 記憶體限制
}############ sphinx 服務程序 ########
searchd
{
#listen = 9312 ### 監聽端口,在此版本開始,官方已在IANA獲得正式授權的9312端口,以前版本預設的是3312log = /usr/local/sphinx/var/log/searchd.log #### 服務程序日志 ,一旦sphinx出現異常,基本上可以從這裡查詢有效資訊,輪換(rotate)出的問題一般可在此尋到答案
query_log = /usr/local/sphinx/var/log/query.log ### 用戶端查詢日志,筆者注:若欲對一些關鍵詞進行統計,可以分析此日志檔案
read_timeout = 5 ## 請求逾時
max_children = 30 ### 同時可執行的最大searchd 程序數
pid_file = /usr/local/sphinx/var/log/searchd.pid #######程序ID檔案
max_matches = 1000 ### 查詢結果的最大傳回數
seamless_rotate = 1 ### 是否支援無縫切換,做增量索引時通常需要
}3.3、建立索引檔案
[root@localhost sphinx]# bin/indexer -c etc/sphinx.conf article ### 建立索引檔案的指令
Sphinx 0.9.9-release (r2117)
Copyright (c) 2001-2009, Andrew Aksyonoffusing config file ‘etc/sphinx.conf’…
indexing index ‘article’…
collected 1000 docs, 0.2 MB
sorted 0.4 Mhits, 99.6% done
total 1000 docs, 210559 bytes
total 3.585 sec, 58723 bytes/sec, 278.89 docs/sec
total 2 reads, 0.031 sec, 1428.8 kb/call avg, 15.6 msec/call avg
total 11 writes, 0.032 sec, 671.6 kb/call avg, 2.9 msec/call avg
[root@localhost sphinx]#
出現以上代表已經索引成功,若不成功的話請根據提示的錯誤修改配置檔案,或到​​​這裡​​提問,我看到後會盡快解決4.應用
4.1 在CLI上測試
在上一步中,我們建立了索引,現在我們對剛建立的索引進行測試。測試有兩種方式:CLI端和API調用
在CLI端上指令測試是使用sphinx自帶的搜尋指令:search
###### 在article索引上檢索 “北京”關鍵詞 ########
[root@localhost sphinx]# bin/search -c etc/sphinx.conf 北京
Sphinx 0.9.9-release (r2117)
Copyright (c) 2001-2009, Andrew Aksyonoffusing config file ‘etc/sphinx.conf’…
index ‘article’: query ‘北京 ‘: returned 995 matches of 995 total in 0.008 secdisplaying matches:
1. document=76, weight=2, cat_id=1, member_id=2, created=Sat Jan 23 19:05:09 2010
id=76
title=??????????
cat_id=1
member_id=2
content=????????????????????????????????
created=1264244709
2. document=85, weight=2, cat_id=1, member_id=2, created=Sat Jan 23 19:05:09 2010
id=85
title=????????????
cat_id=1
member_id=2
content=??▒????????????▒????????▒????▒?????????????????????????????
created=1264244709
…..這裡省略….
20. document=17, weight=1, cat_id=1, member_id=2, created=Sat Jan 23 19:05:09 2010
id=17
title=????????????
cat_id=1
member_id=2
content=??????????????????????????????????????????????????????????
created=1264244709words:
1. ‘北京’: 995 documents, 999 hits至此,可以看到,我們已經檢索出所有有關“北京”的資訊
注意:這裡我使用的是putty的用戶端,在用戶端編碼設定的是utf-8,這個是測試的前提條件
4.2 API調用
在本例中,我使用PHP的api來測試,在測試前,先啟動sphinx服務程序,并對centos的防火牆做好9312端口的開放
[root@localhost sphinx]# bin/searchd -c etc/sphinx.conf & ### 使sphinx在背景運作
[1] 5759
[root@localhost sphinx]# Sphinx 0.9.9-release (r2117)
Copyright (c) 2001-2009, Andrew Aksyonoffusing config file ‘etc/sphinx.conf’…
listening on all interfaces, port=9312[1]+ Done bin/searchd -c etc/sphinx.conf
php測試代碼:
<?php
header(‘Content-type:text/html;charset=utf-8′);
?><form name=”form1″ method=”get” action=”">
<label>
<input style=”width:400px;” type=”text” name=”keyword”>
</label>
<label>
<input type=”submit” name=”Submit” value=”sphinx搜尋”>
</label>
</form><?php
$keyword = $_GET['keyword'];
if (trim($keyword)==”) {
die(‘請輸入關鍵詞’);
}
else {
echo ‘關鍵詞是:’.$keyword;
}require “sphinxapi.php”;
$cl = new SphinxClient();
$cl->SetServer(’192.168.1.150′, 9312); //注意這裡的主機
#$cl->SetMatchMode(SPH_MATCH_EXTENDED); //使用多字段模式
//dump($cl);
$index=”article”;
$res = $cl->Query($keyword, $index);
$err = $cl->GetLastError();
dump($res);
function dump($var)
{
echo ‘<pre>’;
var_dump($var);
echo ‘</pre>’;
}
?>      

檢索“北京”dump後的結果是如下:

array(10) {
  ["error"]=>
  string(0) ""
  ["warning"]=>
  string(0) ""
  ["status"]=>
  int(0)
  ["fields"]=>
  array(2) {
    [0]=>
    string(5) "title"
    [1]=>
    string(7) "content"
  }
  ["attrs"]=>
  array(3) {
    ["cat_id"]=>
    int(1)
    ["member_id"]=>
    int(1)
    ["created"]=>
    int(2)
  }
  ["matches"]=>
  array(20) {
    [76]=>
    array(2) {
      ["weight"]=>
      string(1) "2"
      ["attrs"]=>
      array(3) {
        ["cat_id"]=>
        string(1) "1"
        ["member_id"]=>
        string(1) "2"
        ["created"]=>
        string(10) "1264244709"
      }
    }
  .....這裡省略.....
    [17]=>
    array(2) {
      ["weight"]=>
      string(1) "1"
      ["attrs"]=>
      array(3) {
        ["cat_id"]=>
        string(1) "1"
        ["member_id"]=>
        string(1) "2"
        ["created"]=>
        string(10) "1264244709"
      }
    }
  }
  ["total"]=>
  string(3) "995"
  ["total_found"]=>
  string(3) "995"
  ["time"]=>
  string(5) "0.008"
  ["words"]=>
  array(1) {
    ["北京"]=>
    array(2) {
      ["docs"]=>
      string(3) "995"
      ["hits"]=>
      string(3) "999"
    }
  }
}      

至此PHP已可調用出結果!

附錄

這是本人對sphinx寫的入門手冊,也為自己存檔使用。為寫本文,特重新安裝了一遍Sphinx,并建立mysql表加入1000條記錄,動手重複了一下所有

過程。如有錯誤或疑問請到以下位址回報,謝謝!

歡迎到​​​sphinx中文站(www.sphinxsearch.org)​​讨論sphinx的相關問題,交流你我的思想!