Sphinx 是由俄羅斯人Andrew Aksyonoff開發的一個全文檢索引擎。意圖爲其餘應用提供高速、低空間佔用、高結果 相關度的全文搜索功能。Sphinx能夠很是容易的與SQL數據庫和腳本語言集成。當前系統內置MySQL和PostgreSQL 數據庫數據源的支持,也支持從標準輸入讀取特定格式 的XML數據。經過修改源代碼,用戶能夠自行增長新的數據源(例如:其餘類型的DBMS 的原生支持)
1.2.Sphinx的特性php
* 高速的創建索引(在當代CPU上,峯值性能可達到10 MB/秒);
* 高性能的搜索(在2 – 4GB 的文本數據上,平均每次檢索響應時間小於0.1秒);
* 可處理海量數據(目前已知能夠處理超過100 GB的文本數據, 在單一CPU的系統上可 處理100 M 文檔);
* 提供了優秀的相關度算法,基於短語類似度和統計(BM25)的複合Ranking方法;
* 支持分佈式搜索;
* 支持短語搜索
* 提供文檔摘要生成
* 可做爲MySQL的存儲引擎提供搜索服務;
* 支持布爾、短語、詞語類似度等多種檢索模式;
* 文檔支持多個全文檢索字段(最大不超過32個);
* 文檔支持多個額外的屬性信息(例如:分組信息,時間戳等);
* 支持斷詞;java
1.3.Sphinx中文分詞mysql
中 文的全文檢索和英文等latin系列不同,後者是根據空格等特殊字符來斷詞,而中文是根據語義來分詞。目前大多數數據庫還沒有支持中文全文檢索,如 Mysql。故,國內出現了一些Mysql的中文全文檢索的插件,作的比較好的有hightman的中文分詞。Sphinx若是須要對中文進行全文檢索, 也得須要一些插件來補充。其中我知道的插件有 coreseek 和 sfc 。c++
* Coreseek是如今用的最多的基於sphinx中文全文檢索,它提供了爲Sphinx設計的中文分詞包LibMMSeg 。並提供了多個系統的二進制發行版,其中有rpm,deb及windows下的二進制包。另外,coreseek也爲sphinx貢獻了如下事項:
oGBK編碼的數據源支持
o採用Chih-Hao Tsai MMSEG算法的中文分詞器
o中文使用手冊
* sfc(sphinx-for-chinese)是由網友happy兄提供的另一箇中文分詞插件。其中文詞典採用的是xdict。據其介紹,通過測試, 目前版本在索引速度上(Linux 測試平臺)基本上可以達到索引UTF-8英文的一半,即官方宣稱速度的一半。(時間主要是消耗在分詞上)。程序員
* 此外,若是你對中文分詞不感興趣。或者說僅須要實現相似sql中like的功能,如: select * from product where prodName like ‘%手機%’。sphinx也不會讓你失望,這個或許就是官網對中文的簡單實現——直接對字索引。而且搜索速度還不錯^_^ 。算法
本文會對以上三種中文應用進行測試,並以文檔的方式記錄下來,這也許正是本文檔的重點。
2.安裝配置實例
2.1在GNU/Linux/unix系統上安裝sql
Sphinx在mysql上的應用有兩種方式:
①、採用API調用,如使用PHP、java等的API函數或方法查詢。優勢是可沒必要對mysql從新編譯,服務端進程「低耦合」,且程序可靈活、方便的調用;
缺點是如已有搜索程序的條件下,需修改部分程序。推薦程序員使用。
②、使用插件方式(sphinxSE)把sphinx編譯成一個mysql插件並使用特定的sql語句進行檢索。其特色是,在sql端方便組合,且能直接返回數據給客戶端
沒必要二次查詢(注),在程序上僅須要修改對應的sql,但這對使用框架開發的程序很不方便,好比使用了ORM。另外還須要對mysql進行從新編譯,且須要mysql-5.1以上版本
支持插件存儲。系統管理員可以使用這種方式
二次查詢注:到如今發佈版本爲止——sphinx-2.0.3-release,sphinx在檢索到結果後只能返回記錄的ID,而非要查的sql數據,故須要從新根據這些ID再次從數據庫中查詢。數據庫
本文采用的是第一種方式vim
在*nix系統下安裝,首先須要如下一些軟件支持windows
軟件環境:
* 操做系統:Centos-5.6
* 數據庫:mysql-5.5.17-3.el5 mysql-devel(若是要使用sphinxSE插件存儲請使用mysql-5.1以上版本)
* 編譯軟件:yum -y install make gcc g++ gcc-c++ libtool autoconf automake imake libxml2-devel expat-devel
* Sphinx :Sphinx-2.0.3 (最新版 )
3.配置實例
3.一、數據源。
這裏咱們採用 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.二、配置文件
* [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,sfc
charset_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端口,之前版本默認的是3312
log = /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.三、創建索引文件
[root@localhost sphinx]# bin/indexer -c etc/sphinx.conf article ### 創建索引文件的命令
Sphinx 0.9.9-release (r2117)
Copyright (c) 2001-2009, Andrew Aksyonoff
using 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 Aksyonoff
using config file ‘etc/sphinx.conf’…
index ‘article’: query ‘北京 ‘: returned 995 matches of 995 total in 0.008 sec
displaying 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=1264244709
words:
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 Aksyonoff
using config file ‘etc/sphinx.conf’…
listening on all interfaces, port=9312
[1]+ Done bin/searchd -c etc/sphinx.conf
php測試代碼:
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 ‘
‘;
}
?>
檢索「北京」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已可調用出結果!