1. 程式人生 > >Sphinx中文分詞詳細安裝配置及API呼叫實戰手冊

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程序已經開啟的話,應先關閉)

#生成goods索引[需要確保要連線的主機的MySQL資料庫正常執行,並且3306埠可以訪問]
1 /usr/local/sphinx-for-chinese-1.10.1/bin/indexer -c /usr/local/sphinx-for-chinese-1.10.1/etc/sphinx.conf goods
#如果配置檔案裡有多個索引,需要一次生成使用--all引數
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 &      #執行後記得再按回車
# 防火牆需要開放9312埠供外部訪問9312埠(3306是MySQL的埠)
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檔案裡面有包括實時索引,增量索引等很多內容,英文原版的,很詳細