Sphinx中文分詞詳細安裝配置及API呼叫實戰手冊
這幾天專案中需要重新做一個關於商品的全文搜尋功能,於是想到了用Sphinx,因為需要中文分詞,所以選擇了Sphinx for chinese,當然你也可以選擇coreseek,建議這兩個中選擇一個,暫時不要選擇原版Sphinx(對中文的支援不是很好).又因為伺服器所用MySQL在當時編譯時並沒有編譯Sphinx擴充套件,而重新編譯MySQL並加入Sphinx暫時又無法實現(專案用到了多臺伺服器,在不影響現有業務的情況下不可能去重新編譯MySQL的),所以採用的是程式通過API來外部呼叫Sphinx.Sphinx自帶的API有PHP,Python,Ruby,Java等眾多版本,所以基本也夠用了,本人使用的程式語言是PHP所以下文的條用示例採用的是PHP版的API.
一.安裝及配置Sphinx及準備測試資料
1.安裝前的準備工作
(1)請確認安裝了MySQL,Gcc及常用的開發環境包
(2)下載sphinx-for-chinese-1.10.1(sphinx-for-chinese官方下載)及中文分詞詞典xdict_1.1
1 |
$ cd
/usr/ local /src |
2 |
for -chinese.googlecode.com/files/sphinx- for -chinese-1.10.1-dev-r2287. tar .gz
|
3 |
for -chinese.googlecode.com/files/xdict_1.1. tar .gz |
2.安裝sphinx-for-chinese-1.10.1
1 |
$ cd
/usr/ local /src |
2 |
$ tar
zxvf sphinx- for -chinese-1.10.1-dev-r2287. tar .gz
|
3 |
$ cd
sphinx- for -chinese-1.10.1-dev-r2287
|
4 |
#MySQL安裝在預設位置的使用如下命令 |
5 |
$ ./configure --prefix=/usr/ local /sphinx- for -chinese-1.10.1 --with-mysql |
如果出現如下圖所示錯誤,表明MySQL不是安裝在預設位置,請執行下面的命令
#如果MySQL不是安裝在預設位置(特別是自己編譯MySQL的,請注意),請指定MySQL的相關位置,主要是MySQL的include和lib目錄(Sphinx編譯的時候要用到裡面的.h標頭檔案),--with-mysql-includes及--with-mysql-libs就是為了指定這兩個位置的
1 |
./configure --prefix=/usr/ local /sphinx- for -chinese-1.10.1 --with-mysql-includes=/usr/ local /webserver/mysql/include/mysql
--with-mysql-libs=/usr/ local /webserver/mysql/lib/mysql |
顯示如下圖所示內容時,表示可以接著執行下面的make及make install命令
1 |
$ make |
2 |
$ make
install |
3 |
#最後執行命令 |
4 |
$ ls
/usr/ local /sphinx- for -chinese-1.10.1/ |
如果顯示bin,etc和var三個目錄表示安裝成功
3.讓Sphinx支援中文分詞
1 |
$ cd
/usr/ local /src |
2 |
$ tar
zxvf xdict_1.1. tar .gz
|
3 |
$ /usr/ local /sphinx- for -chinese-1.10.1/bin/mkdict xdict_1.1.txt xdict_1.1 |
如果提示bin/mkdict: error while loading shared libraries: libmysqlclient.so.16等錯誤(以下命令中的libmysqlclient.so.16.0.0的位置取決於我們mysql編譯安裝的位置)
1 |
ln -s /usr/ local /webserver/mysql/lib/mysql/libmysqlclient.so.16.0.0 /usr/lib/libmysqlclient.so.16 |
再次執行
1 |
$ /usr/ local /sphinx- for -chinese-1.10.1/bin/mkdict xdict_1.1.txt xdict_1.1
|
2 |
#提示Chinese dictionary was successfully created!表示中文分詞詞典生成成功
|
3 |
$ cp
xdict_1.1 /usr/ local /sphinx- for -chinese-1.10.1/etc/xdict_1.1 |
4.配置Sphinx
1 |
vi /usr/ local /sphinx- for -chinese-1.10.1/etc/sphinx.conf |
輸入以下內容
001 |
# sphinx基本配置 |
002 |
# 索引源 |
003 |
source goods_src
|
004 |
{ |
005 |
# 資料庫型別
|
006 |
type
= mysql |
007 |
# MySQL主機IP
|
008 |
sql_host = localhost
|
009 |
# MySQL使用者名稱
|
010 |
sql_user = sphinxuser
|
011 |
# MySQL密碼
|
012 |
sql_pass = sphinxpass
|
013 |
# MySQL資料庫
|
014 |
sql_db = sphinx
|
015 |
# MySQL埠(如果防火牆有限制,請開啟)
|
016 |
sql_port= 3306
|
017 |
# MySQL sock檔案設定(預設為/tmp/mysql.sock,如果不一樣,請指定)
|
018 |
sql_sock = /tmp/mysql.sock
|
019 |
# MySQL檢索編碼(資料庫非utf8的很可能檢索不到)
|
020 |
sql_query_pre = SET NAMES UTF8
|
021 |
# 獲取資料的SQL語句
|
022 |
sql_query = SELECT goods_id,goods_id AS goods_id_new,goods_name,goods_color,goods_name AS goods_name_search,goods_color AS goods_color_search From goods_test
|
023 |
# 以下是用來過濾或條件查詢的屬性(以下欄位顯示在查詢結果中,不在下面的欄位就是搜尋時要搜尋的欄位,如SQL語句中的goods_color_search,goods_name_search)
|
024 |
# 無符號整型
|
025 |
#goods_id為主鍵,如果加在這裡在生成索引的時候會報attribute 'goods_id' not found,這裡用goods_id_new來變通
|
026 |
sql_attr_uint = goods_id_new
|
027 |
# 字串型別
|
028 |
sql_attr_string = goods_name
|
029 |
sql_attr_string = goods_color
|
030 |
# 用於命令介面端(CLI)呼叫的測試(一般來說不需要)
|
031 |
#sql_query_info = SELECT * FROM goods_test Where goods_id = $goods_id;
|
032 |
} |
033 |
# 索引 |
034 |
index goods |
035 |
{ |
036 |
# 索引源宣告
|
037 |
source
= goods_src |
038 |
# 索引檔案的存放位置
|
039 |
path = /usr/ local /sphinx- for -chinese-1.10.1/var/data/goods |
040 |
# 檔案儲存模式(預設為extern)
|
041 |
docinfo = extern
|
042 |
# 快取資料記憶體鎖定
|
043 |
mlock = 0
|
044 |
# 馬氏形態學(對中文無效)
|
045 |
morphology = none
|
046 |
# 索引詞最小長度
|
047 |
min_word_len = 1
|
048 |
# 資料編碼(設定成utf8才能索引中文)
|
049 |
charset_type = utf-8
|
050 |
# 中文分詞詞典
|
051 |
chinese_dictionary = /usr/ local /sphinx- for -chinese-1.10.1/etc/xdict_1.1
|
052 |
# 最小索引字首長度
|
053 |
min_prefix_len = 0
|
054 |
# 最小索引中綴長度
|
055 |
min_infix_len = 1
|
056 |
# 對於非字母型資料的長度切割(for CJK indexing)
|
057 |
ngram_len = 1
|
058 |
# 對否對去除使用者輸入查詢內容的html標籤
|
059 |
html_strip = 0
|
060 |
} |
061 |
# 索引器設定 |
062 |
indexer |
063 |
{ |
064 |
# 記憶體大小限制 預設是 32M, 最大 2047M, 推薦為 256M 到 1024M之間
|
065 |
mem_limit = 256M
|
066 |
} |
067 |
# sphinx服務程序search的相關配置 |
068 |
searchd |
069 |
{ |
070 |
# 監測埠及形式,一下幾種均可,預設為本機9312埠
|
071 |
# listen = 127.0.0.1
|
072 |
# listen = 192.168.0.1:9312
|
073 |
# listen = 9312
|
074 |
# listen = /var/run/searchd.sock
|
075 |
# search程序的日誌路徑
|
076 |
log = /usr/ local /sphinx- for -chinese-1.10.1/var/log/searchd.log
|
077 |
# 查詢日誌地址
|
078 |
query_log = /usr/ local /sphinx- for -chinese-1.10.1/var/log/query.log
|
079 |
# 讀取超時時間
|
080 |
read_timeout = 5
|
081 |
# 請求超時市時間
|
082 |
client_timeout = 300
|
083 |
# searche程序的最大執行數
|
084 |
max_children = 30
|
085 |
# 程序ID檔案
|
086 |
pid_file = /usr/ local /sphinx- for -chinese-1.10.1/var/log/searchd.pid
|
087 |
# 最大的查詢結果返回數
|
088 |
max_matches = 1000
|
089 |
# 是否支援無縫切換(做增量索引時需要)
|
090 |
seamless_rotate = 1
|
091 |
# 在啟動執行時是否提前載入所有索引檔案
|
092 |
preopen_indexes = 0
|
093 |
# 是否釋放舊的索引檔案
|
094 |
unlink_old = 1
|
095 |
# MVA跟新池大小(預設為1M)
|
096 |
mva_updates_pool = 1M
|
097 |
# 最大允許的網路包大小(預設8M)
|
098 |
max_packet_size = 8M
|
099 |
# 每個查詢最大允許的過濾器數量(預設256)
|
100 |
max_filters = 256
|
101 |
#每個過濾器最大允許的值的個數(預設4096)
|
102 |
max_filter_values = 4096
|
103 |
# 每個組的最大查詢數(預設為32)
|
104 |
max_batch_queries = 32
|
105 |
} |
106 |
# Sphinx配置檔案結束 |
中文在linux下可能會看到亂碼,不用管
5.建立測試資料庫並新增測試內容(請先連上自己的MySQL資料庫)
在MySQL中執行如下命令
01 |
mysql> create
database sphinx collate
'utf8_general_ci' ; |
02 |
mysql> grant
all privileges
on sphinx.* to
'sphinxuser' @ ''
identified by 'sphinxpass' ; |
03 |
mysql> grant
all privileges
on sphinx.* to
'sphinxuser' @ 'localhost'
identified by
'sphinxpass' ; |
04 |
mysql> use sphinx; |
05 |
mysql> CREATE
TABLE IF NOT
EXISTS `goods_test` ( |
06 |
`goods_id` int (10) unsigned
NOT NULL
AUTO_INCREMENT COMMENT '商品id' , |
07 |
`goods_name` varchar (255)
NOT NULL
COMMENT '商品名稱' , |
08 |
`goods_color` varchar (60)
NOT NULL
COMMENT '商品顏色' , |
09 |
PRIMARY KEY
(`goods_id`) |
10 |
) ENGINE=MyISAM DEFAULT
CHARSET=utf8 COMMENT= '商品表,sphinx示例'
AUTO_INCREMENT=11 ; |
11 |
mysql> INSERT
INTO `goods_test` (`goods_id`, `goods_name`, `goods_color`)
VALUES |
12 |
(1, '熱賣時尚雙肩揹包' ,
'黑色' ), |
13 |
(2, '熱賣時尚電腦雙肩揹包' ,
'灰色' ), |
14 |
(3, '繽紛炫動時尚化妝包' ,
'黑色' ), |
15 |
(4, '繽紛炫動時尚化妝包' ,
'藍色' ), |
16 |
(5, '繽紛炫動時尚化妝包' ,
'粉紅' ), |
17 |
(6, '極致性感 女款襯衫' ,
'黑色' ), |
18 |
(7, '個性宣言 男款短袖襯衫' ,
'藍色' ), |
19 |
(8, '個性宣言 男款短袖襯衫' ,
'紅色' ), |
20 |
(9, '個性宣言 男款短袖襯衫' ,
'綠色' ), |
21 |
(10, '個性宣言 男款短袖襯衫' ,
'黑色' ); |
好了,萬事俱備了,可以開始實戰操作Sphinx了
二.實戰操作Sphinx
1.建立索引(如果配置檔案有改動,應該重新生成索引檔案,如果下面第3點中的searchd程序已經開啟的話,應先關閉)
1 |
/usr/ local /sphinx- for -chinese-1.10.1/bin/indexer -c /usr/ local /sphinx- for -chinese-1.10.1/etc/sphinx.conf
goods |
1 |
/usr/ local /sphinx- for -chinese-1.10.1/bin/indexer -c /usr/ local /sphinx- for -chinese-1.10.1/etc/sphinx.conf
--all |
2.在linux命令列下測試搜尋
1 |
/usr/ local /sphinx- for -chinese-1.10.1/bin/search -c /usr/ local /sphinx- for -chinese-1.10.1/etc/sphinx.conf
個性黑色 |
搜尋結果如下圖示:
3.開啟守護程序(供API呼叫,如果配置檔案改動,應重新啟動這個程序,不然搜到的資料不是最新)
1 |
/usr/ local /sphinx- for -chinese-1.10.1/bin/searchd -c /usr/ local /sphinx- for -chinese-1.10.1/etc/sphinx.conf
& #執行後記得再按回車 |
1 |
/sbin/iptables -I INPUT -p tcp --dport 3306 -j ACCEPT |
2 |
/sbin/iptables -I INPUT -p tcp --dport 9312 -j ACCEPT |
3 |
/etc/rc.d/init.d/iptables save |
三.外部API呼叫(PHP版)
注意使用時前提是執行了以上的步驟3.開啟守護程序,而且防火牆也開啟了9312埠
1.把/usr/local/src/sphinx-for-chinese-1.10.1-dev-r2287/api/sphinxapi.php弄出來,和下面第2點中的search.php放在同級目錄(這個只是示例,放在哪裡都可以,包含的時候找到正確的sphinxapi.php的位置即可)
2.編輯search.php檔案,內容如下(具體內容請讀者自己定,我這裡只是示例)
01 |
<?php |
02 |
header ( 'Content-Type: text/html;charset="UTF-8"'
); |
03 |
if ( $_GET ) { |
04 |
// 關鍵詞 |
05 |
$keyword
= urldecode ( trim ( strip_tags
( $_GET
[ 'keyword' ] ) ) ); |
06 |
if
( $keyword ) { |
07 |
// 包含Sphinx的api檔案 |
08 |
require_once
'sphinxapi.php' ; |
09 |
// sphinx伺服器地址 |
10 |
$server
= '192.168.128.130' ; |
11 |
// 埠 |
12 |
$port
= 9312; |
13 |
// 索引名 為*時表示搜尋所有索引 |
14 |
$indexName
= 'goods' ; |
15 |
// 分頁頁碼 |
16 |
$page
= intval
( $_GET [ 'page' ] ) > 1 ?
intval ( $_GET
[ 'page' ] ) : 1; |
17 |
// 每頁顯示的數量 |
18 |
$pageSize
= 30; |
19 |
$sphinx
= new
SphinxClient (); |
20 |
// 建立連線 |
21 |
$sphinx ->SetServer (
$server , $port
); |
22 |
// 連線超時時間(非常必要,比如sphinx伺服器掛了等異常情況) 單位為s,秒 |
23 |
$sphinx ->SetConnectTimeout ( 3 ); |
24 |
// 最大查詢時間 單位為ms,毫秒 |
25 |
$sphinx ->SetMaxQueryTime ( 2000 ); |
26 |
// 按分頁取結果 |
27 |
$sphinx ->SetLimits ( ( $page
- 1) * $pageSize ,
$pageSize ); //第一個引數為offset,第二個引數為limit |
28 |
// 模式 |
29 |
// $sphinx->SetMatchMode(SPH_MATCH_EXTENDED); |
30 |
// 取到的原始資料 |
31 |
$orgDatas
= $sphinx ->Query (
$keyword , $indexName
); |
32 |
// 除錯用,如果有錯誤的話,可以列印$errors的值 |
33 |
$errors
= $sphinx ->GetLastError (); |
34 |
var_dump (
$errors ); |
35 |
echo
'<pre>' ; |
36 |
var_dump (
$orgDatas ); |
37 |
/* // 下面是對結果的處理 |
38 |
$datas = array('goods'=>array(),'total'=>0); |
39 |
if ($orgDatas['total'] > 0) { |
40 |
$datas['total'] = $orgDatas['total']; |
41 |
foreach ($orgDatas['matches'] AS $val) { |
42 |
$val['attrs']['goods_id'] = $val['attrs']['goods_id_new']; |
43 |
unset($val['attrs']['goods_id_new']); |
44 |
$datas['goods'][] = $val['attrs']; |
45 |
} |
46 |
} |
47 |
var_dump($datas); |
48 |
*/ |
49 |
} |
50 |
} else
{ |
51 |
echo
'<form method="get"><input type="type" name="keyword"><input type="submit" value="商品搜尋"></form>' ; |
52 |
} |
53 |
?> |
更多詳細配置請參看/usr/local/sphinx-for-chinese-1.10.1/etc/sphinx.conf.dist檔案裡面有包括實時索引,增量索引等很多內容,英文原版的,很詳細