Sphinx學習筆記(一)

    最近負責一個項目,須要用到全文檢索,個人環境大致以下:node

 
    一、數據保存在MySQL中
    二、須要支持中文檢索
    三、儘量的簡單
 
    選擇了Sphinx,至於solr和Elasticsearch,看主頁的介紹,它們對分佈式、均衡等方面的支持很是好,只不過它們的安裝包太大了,用起來挺不方便的,因此才放棄了它們,不過等有機會還能夠研究一下。
 
    基本步驟以下:
   一、 安裝:Sphinx的主頁是http://sphinxsearch.com/,目前版本爲2.2.8,下載界面爲http://sphinxsearch.com/downloads/release/,分爲32位和64位版本,還分爲windows、debian/ubuntu,Fedora/Centos版本,也能夠直接下載源代碼,進行編譯安裝,我主要在windows上測試,在Centos上部署,簡述過程以下
      1)Windows 8.1 X64 , sphinx 2.2.8 (Win64 binaries w/MySQL+PgSQL+libstemmer+id64 support)
      將壓縮包解壓縮到d:\blue下,解壓縮後sphinx根目錄爲D:\blue\sphinx-2.2.8-release-win64-full。
      修改配置文件sphinx-min.conf.in,相對簡單一下
#
# Minimal Sphinx configuration sample (clean, simple, functional)
#
#數據源,src1爲名字,後面會引用這個名字
source src1
{
 type = mysql
 
 sql_host = localhost
 sql_user = test
 sql_pass =
 sql_db = test
 sql_port = 3306 # optional, default is 3306
 
 sql_query = \
  SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
  FROM documents
 
 sql_attr_uint = group_id
 sql_attr_timestamp = date_added
}
 
#test1爲索引名稱,sphinx檢索時須要這個名字,至關於關係數據庫中的table
index test1
{
 source = src1 #引用的數據源名稱
 path = @CONFDIR@/data/test1
}
 
 
index testrt
{
 type = rt
 rt_mem_limit = 128M
 
 path = @CONFDIR@/data/testrt
 
 rt_field = title
 rt_field = content
 rt_attr_uint = gid
}
 
 
indexer
{
 mem_limit = 128M
}
 
 
searchd
{
 listen = 9312
 listen = 9306:mysql41
 log = @CONFDIR@/log/searchd.log
 query_log = @CONFDIR@/log/query.log
 read_timeout = 5
 max_children = 30
 pid_file = @CONFDIR@/log/searchd.pid
 seamless_rotate = 1
 preopen_indexes = 1
 unlink_old = 1
 workers = threads # for RT to work
 binlog_path = @CONFDIR@/data
}
       具體修改步驟以下,修改source src1下的mysql鏈接信息,包括主機、用戶名、密碼、數據庫、端口,sql_query是數據源中的sql,這裏是從mysql中抽取數據,sql_attr_*是用來分組排序用的,若是咱們須要對一些字段進行排序操做,須要在這裏定義,另外須要替換@CONFDIR@爲你想要的目錄,個人修改以下
#
# Minimal Sphinx configuration sample (clean, simple, functional)
#
 
source src1
{
 type = mysql
 
 sql_host = localhost
 sql_user = root
 sql_pass = 
 sql_db = sphinx
 sql_port = 3306 # optional, default is 3306
 
 sql_query = \
  SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
  FROM documents
 
 sql_attr_uint = group_id
 sql_attr_timestamp = date_added
 sql_query_pre = SET NAMES utf8
}
 
 
index test1
{
 source = src1
 path = D:/blue/sphinx_data/data/test1
 
 ngram_len = 1
 ngram_chars = U+4E00..U+9FBB, U+3400..U+4DB5, U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27, U+FA28, U+FA29, U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043, U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057, U+3059, U+305B, U+305D, U+305F, U+3061, U+3063, U+3066, U+3068, U+306A..U+306F, U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, U+3085, U+3087, U+3089..U+308E, U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7, U+30A9, U+30AD, U+30AF, U+30B3, U+30B5, U+30BB, U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB, U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3, U+30E5, U+30E7, U+30EE, U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5, U+31F6, U+31F7, U+31F8, U+31F9, U+31FA, U+31FB, U+31FC, U+31FD, U+31FE, U+31FF, U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C, U+A492..U+A4C6
 
}
 
 
index testrt
{
 type = rt
 rt_mem_limit = 128M
 
 path = D:/blue/sphinx_data/data/testrt
 
 rt_field = title
 rt_field = content
 rt_attr_uint = gid
}
 
 
indexer
{
 mem_limit = 128M
}
 
 
searchd
{
 listen = 9312
 listen = 9306:mysql41
 log = D:/blue/sphinx_data/log/searchd.log
 query_log = D:/blue/sphinx_data/log/query.log
 read_timeout = 5
 max_children = 30
 pid_file = D:/blue/sphinx_data/log/searchd.pid
 seamless_rotate = 1
 preopen_indexes = 1
 unlink_old = 1
 workers = threads # for RT to work
 binlog_path = D:/blue/sphinx_data/data
}
 
    修改的內容如黑體字所示,須要注意的是sql_query_pre, ngram_len,ngram_chars,這些都是支持中文檢索必須的,若是沒有的話,沒法支持中文,另外將@CONFDIR@替換爲d:\blue\sphinx_data,另外這個目錄下創建兩個目錄data和log,不知道什麼緣由,系統沒法自動建立這兩個目錄,會出錯。
    另外在本機新建一個sphinx數據庫,字符集選擇utf-8,而後運行D:\blue\sphinx-2.2.8-release-win64-full下的example.sql,須要注意將其中的數據庫前綴test.更換爲sphinx.,表示在sphinx數據庫中建立表,建立以後,在sphinx下檢查一下,看是否存在documents和tags兩張表。
    而後在D:\blue\sphinx-2.2.8-release-win64-full\bin下,運行indexer -c ..\sphinx-min.conf.in --all ,以下
D:\blue\sphinx-2.2.8-release-win64-full\bin>indexer -c ..\sphinx-min.conf.in --all
Sphinx 2.2.8-id64-release (r4942)
Copyright (c) 2001-2015, Andrew Aksyonoff
Copyright (c) 2008-2015, Sphinx Technologies Inc (http://sphinxsearch.com)
 
using config file '..\sphinx-min.conf.in'...
indexing index 'test1'...
collected 4 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4 docs, 33882 bytes
total 0.121 sec, 278900 bytes/sec, 32.92 docs/sec
skipping non-plain index 'testrt'...
total 3 reads, 0.000 sec, 12.0 kb/call avg, 0.0 msec/call avg
total 12 writes, 0.001 sec, 5.7 kb/call avg, 0.1 msec/call avg
須要注意的是,若是須要創建的索引已經被使用,即已經啓動了searchd服務,就須要增長--rotate參數,相似於
indexer -c ..\sphinx-min.conf.in --all --rotate

    而後在同一目錄下運行 searchd -c ..\sphinx-min.conf.in,以下mysql

D:\blue\sphinx-2.2.8-release-win64-full\bin>searchd -c ..\sphinx-min.conf.in
Sphinx 2.2.8-id64-release (r4942)
Copyright (c) 2001-2015, Andrew Aksyonoff
Copyright (c) 2008-2015, Sphinx Technologies Inc (http://sphinxsearch.com)
 
using config file '..\sphinx-min.conf.in'...
listening on all interfaces, port=9312
listening on all interfaces, port=9306
precaching index 'test1'
rotating index 'test1': success
precaching index 'testrt'
precached 2 indexes in 0.045 sec

    沒有什麼錯誤,須要注意的是,須要先建立索引,才能啓動服務,不然可能會出錯,searchd命令也能夠安裝爲服務,之後使用起來會更加方便,這裏這麼作也是爲了看究竟是否配置成功,不然系統服務出錯,咱們看不到錯誤緣由。linux

    查看searchd的輸出或者sphinx-min.conf.in的searchd的配置項,能夠知道sphinx在兩個端口監聽,9312,9306,其中9312是Sphinx API訪問的端口,9306是SphinxQL的,SphinxQL是一個Mysql接口,能夠經過mysql客戶端訪問。
二、SphinxQL
     SPihinxQL是一種mysql接口,能夠經過sql語句來執行查詢,能夠用mysql命令行工具,也可使用mysql的客戶端工具,如HeidiSQL,這個是我經常使用的mysql客戶端,配置鏈接很簡單,用戶名密碼不用填,只要設置主機和端口就能夠了,端口一般爲9306,命令行以下
     >mysql -h localhost -P9306
     下面就可使用SphinxQL了
     mysql中的數據以下
id group_id group_id2 date_added title content
1 1 5 2015/3/27 16:53 test one this is my test document number one. also checking...
2 1 6 2015/3/27 16:53 test two this is my test document number two
3 2 7 2015/3/27 16:53 another doc this is another group
4 2 8 2015/3/27 16:53 doc number four this is to test groups
   運行SphinxQL,
  mysql> select * from test1 where match('my');
+------+----------+------------+
| id   | group_id | date_added |
+------+----------+------------+
|    1 |        1 | 1427446411 |
|    2 |        1 | 1427446411 |
+------+----------+------------+
2 rows in set (0.00 sec)
     能夠看出這裏面並不包含數據,只包含數字字段:id和group_id,因此若是想獲得數據,須要在mysql中從新查詢數據才能獲得結果。
     下面修改一下數據,改爲中文,以下
id group_id group_id2 date_added title content
1 1 5 2015/3/27 16:53 test one this is my test document number one. also checking...
2 1 6 2015/3/27 16:53 test two this is my test document number two
3 2 7 2015/3/27 16:53 another doc 代碼到了必定時間,必須重構,不然會出現問題
4 2 8 2015/3/27 16:53 doc number four 重慶製造到了最後階段了,車體構造已經完成,就等待最後的出廠了
      從新生成索引,
      D:\blue\sphinx-2.2.8-release-win64-full\bin>indexer -c ..\sphinx-min.conf.in --all --rotate
 

Sphinx 2.2.8-id64-release (r4942)git

 

Copyright (c) 2001-2015, Andrew Aksyonoffgithub

 

Copyright (c) 2008-2015, Sphinx Technologies Inc (http://sphinxsearch.com)sql

 
 

using config file '..\sphinx-min.conf.in'...數據庫

 

indexing index 'test1'...npm

 

collected 4 docs, 0.0 MBubuntu

 

sorted 0.0 Mhits, 100.0% donewindows

 

total 4 docs, 303 bytes

 

total 0.086 sec, 3518 bytes/sec, 46.44 docs/sec

 

skipping non-plain index 'testrt'...

 

total 3 reads, 0.000 sec, 0.4 kb/call avg, 0.0 msec/call avg

 

total 12 writes, 0.001 sec, 0.2 kb/call avg, 0.0 msec/call avg

 

rotating indices: successfully sent SIGHUP to searchd (pid=4556).

 
     中文查詢就沒法在mysql命令行中執行了,這是在windows的狀況下,由於其中文字符不是UTF-8,會出現沒法搜索出結果的現象,須要用HeidiSQL之類的,運行查詢,
     select * from test1 where match('重構');
"id" "group_id" "date_added"
"3" "2" "1427446411"
"4" "2" "1427446411"

    這裏面有一個問題,能夠看出id 4實際上並無「重構」這個詞,只是包含「重」「構」這兩個字而已,因此可能沒法知足某些需求,可是好在Sphinx的默認匹配方式是短語類似度,因此理論上來講,包含「重構」這個詞的會排序在前面,簡單測試也是如此,是否一直如此就不知道了。能夠參考這篇文章:http://rainkid.blog.163.com/blog/static/165140840201010277223611/

三、Nodejs查詢Sphinx
   1)Sphinxapi
        首頁在https://github.com/lindory-project/node-sphinxapi/tree/master,安裝方式: npm install sphinxapi
        文檔比較詳細,簡單實用以下
        #sphinx2.js
var SphinxClient = require ("sphinxapi"),
    util = require('util'),
    assert = require('assert');
 
var cl = new SphinxClient();
cl.SetServer('localhost', 9312);
cl.Query('重構','test1', function(err, result) {
        assert.ifError(err);
        console.log(util.inspect(result, false, null, true));
});
運行程序,node sphinx2.js,以下
{ error: '',
  warning: '',
  status: [ 0 ],
  fields: [ 'title', 'content' ],
  attrs:
   [ [ 'group_id', 1 ],
     [ 'date_added', 2 ] ],
  matches:
   [ { id: 3,
       weight: 2,
       attrs: { group_id: 2, date_added: 1427446411 } },
     { id: 4,
       weight: 1,
       attrs: { group_id: 2, date_added: 1427446411 } } ],
  total: 2,
  total_found: 2,
  time: 0.004,
  words:
   [ { word: '重', docs: 2, hits: 2 },
     { word: '構', docs: 2, hits: 2 } ] }
能夠看出和SphinxQL運行的效果同樣,只不過返回的信息更多而已。

    2)SphinxQL

       SphinxQL須要SphinxAPI的支持,因此在安裝sphinxapi包的基礎上,還須要安裝node-mysql包,命令爲npm install mysql
       簡單例子以下
#sphinx.js
var mysql = require('mysql');
 
var connection = mysql.createConnection(
    {
      host      : 'localhost',
      port : '9306'
    }
);
 
connection.connect();
 
var queryString = "SELECT * FROM test1 WHERE MATCH('重構')";
 
connection.query(queryString, function(err, rows, fields) {
    if (err) throw err;
 
    for (var i in rows) {
        console.log(JSON.stringify(rows[i]));
    }
});
 
connection.end();
 
運行程序,node sphinx.js,以下
{"id":3,"group_id":2,"date_added":1427446411}
{"id":4,"group_id":2,"date_added":1427446411}
 
乍看起來,彷佛sphinxapi提供的信息更多,我沒有具體比較過,不過sphinxQL也包含了一些函數,如weight(),能夠返回權重,如執行SELECT *, weight() FROM test1 WHERE MATCH('重構'); 結果以下
"id" "group_id" "date_added" "weight()"
"3" "2" "1427446411" "2557"
"4" "2" "1427446411" "1557"
可知sphinxap提供的權重,彷佛是sphinxQL提供的值除以1000以後的值

  三、CentOS的安裝和使用

       CentOS的使用沒什麼特別的,最好是下載rpm安裝包,過程以下
$ yum install postgresql-libs unixODBC
$ rpm -Uhv sphinx-2.2.8.rhel6.x86_64.rpm
$ service searchd start
具體的使用和Windows是同樣的,沒有什麼區別。

   四、其餘

        1)最好的文檔來源是官方文檔,比較詳細,內容也較多
        2)若是對信息的實時性要求較高,可使用實時索引,具體內容我沒有仔細研究過,之後有機會研究吧
        3)索引合併,若是原數據較多,新增長的數據很少,能夠採用增量更新索引的辦法,命令以下
indexer --merge DSTINDEX SRCINDEX [--rotate]
        srcindex會更新到dstindex上,若是目標索引正在使用,須要使用--rotate參數
        須要注意的是,若是發生重複現象,原始索引的數據並不會刪除,若是要達到這一目的,能夠運行
indexer --merge main delta --merge-dst-range deleted 0 0
        在某些狀況下,這種方式較爲有用,如每隔一小時合併一次索引,晚上重建一次索引,若是數據規模過大,就須要考慮分佈式了,這個問題就比較複雜了,須要另外研究了。
        4)sql_query_pre = SET NAMES utf8 
         這個設置有些奇怪,我在文檔中並無查到這個信息,,可是不設置這個,就沒法生成中文索引,後來仍是在sphinx羣中諮詢了一下,「熊熊熊熊」同窗看了個人配置文件,指出了這個問題,我才得以繼續使用sphinx,不然我都要放棄sphinx了,這裏要對「熊熊熊熊」同窗表示感謝。不知道是否是windows 8的緣由,不過在linux下也須要設置這個參數,不知道爲何。
       5)安裝爲服務(windows 8. 1)
        RPM和DEB包自動安裝服務,在windows下,須要運行seachd命令將其安裝爲服務:
     searchd --install -c D:\blue\sphinx-for-chinese-2.2.1-dev-r4311-win32\sphinf-min.conf.in 服務名
        若是不指定服務名,會在windows服務列表中生成一個名爲search的服務。
        在測試時,最好用searchd命令行運行,不要安裝爲服務,由於沒有輸出會比較麻煩,出了問題很差解決。
        刪除服務: sc delete 服務名
  五、sphinx for chinese的配置問題(windows 8.1)
       sphinx for chinese的版本有點舊了,最新的以下
        其使用方式也比較簡單,須要在配置文件中修改索引項,以下
index test1
{
 source = src1
 path = D:/blue/sphinx_data/data/test1
 docinfo = extern
 charset_type = utf-8
 chinese_dictionary = D:\blue\sphinx-for-chinese-2.2.1-dev-r4311-win32\xdict
}
其中charset_type = utf-8在最新的版本中已經廢棄,由於默認已是utf-8,xdict是一個字典文件
        xdict是一個字典文件,能夠從https://sphinx-for-chinese.googlecode.com/files/xdict_1.1.tar.gz下載,而後解壓縮,用mkdict命令生成字典,以下:bin\mkdict.exe xdict_1.1.txt xdict
      Sphinx for chinese用起來也很方便,可是有一個不同的地方,仍是使用上面的數據,運行SphinxQL,
      select *,weight() from test1 where match('重構');
      "id" "group_id" "date_added" "weight()"
      "3" "2" "1427446411" "1695"
      能夠看出此次能夠精確找到id爲3的數據,沒有搜索到4,可是若是隻搜索單字「重」,是沒有數據的,這是不同的地方。
相關文章
相關標籤/搜索