1. 程式人生 > >sphinx的安裝配置和中文分詞包coreseek

sphinx的安裝配置和中文分詞包coreseek

sphinx在此處下載:

http://sphinxsearch.com/downloads/release/

本次我下的是2.2.4版本

自持中文分詞的包叫做coreseek,其實就是帶了中文分詞外掛的sphinx,在此處下載:

http://www.coreseek.cn/

本次我下的是穩定版3.2.14

先寫個結論,sphinx本身是可以支援中文搜尋的,只是不支援中文分詞,需要安裝中文分詞外掛,coreseek就是一個打包了mmseg中文分詞外掛和sphinx原始碼的安裝包

目前coreseek已經很久不更新了,穩定版3.2.14內帶的的sphinx還是 0.9.9 release版本的;而sphinx可以通過設定為“一元切分模式”來支援搜尋中文

在實際使用中,搜尋非中文的話,sphinx比coreseek要快;搜尋短中文字串的話,開啟了“一元切分模式”的sphinx比coreseek要快;只有在搜尋長中文字串時,coreseek的分詞優勢才能顯現,比sphinx要快

所以根據你的應用場景來選擇用哪個,如果是索引英文、數字、字元較多的資料,就用源生sphinx;如果是索引中文非常多非常長的資料,還是用coreseek吧

下面先來講sphinx的安裝和配置:

把包下載下來,我下的是http://sphinxsearch.com/files/sphinx-2.2.4-release.tar.gz

tar xzvf sphinx-2.2.4-release.tar.gz

cd sphinx-2.2.4-release

./configure --prefix=/usr/local/sphinx/   --with-mysql  --enable-id64 #如果是64位的才加這個選項

make

make install

這樣就裝好了,現在來配置

cp /usr/local/sphinx/etc/sphinx-min.conf.dist /usr/local/sphinx/etc/test.conf

vim /usr/local/sphinx/etc/test.conf

1.   sphinx配置檔案結構介紹

Sphinx的配置檔案結構如下:

Source 源名稱1{     

#新增資料來源,這裡會設定一些連線資料庫的引數比如資料庫的IP、使用者名稱、密碼等

#設定sql_query、設定sql_query_pre、設定sql_query_range等後面會結合例子做詳細介紹

 ……

}

Index 索引名稱1{

     Source=源名稱1

#設定全文索引

     ……

}

Indexer{

#設定Indexer程式配置選項,如記憶體限制等

……

}

Searchd{  

#設定Searchd守護程序本身的一些引數

……

}

Source和Index都可以配置多個。

2.   spinx配置案例詳細解釋

接下來就來針對一個配置案例來做詳細的配置介紹:

#定義一個數據源

source search_main

{

           #定義資料庫型別

   type                 = mysql

           #定義資料庫的IP或者計算機名

   sql_host             = localhost

           #定義連線資料庫的帳號

   sql_user             = root

           #定義連結資料庫的密碼

   sql_pass             = test123

           #定義資料庫名稱

   sql_db               = test

           #定義連線資料庫後取資料之前執行的SQL語句

   sql_query_pre        = SET NAMESutf8

   sql_query_pre        = SET SESSIONquery_cache_type=OFF

           #建立一個sph_counter用於增量索引

   sql_query_pre        = CREATETABLE IF NOT EXISTS sph_counter \

                                      ( counter_id INTEGER PRIMARY KEY NOTNULL,max_doc_id INTEGER NOT NULL)

           #取資料之前將表的最大id記錄到sph_counter表中

   sql_query_pre        = REPLACEINTO sph_counter SELECT 1, MAX(searchid) FROM v9_search

           #定義取資料的SQL,第一列ID列必須為唯一的正整數值

    sql_query            = SELECTsearchid,typeid,id,adddate,data FROM v9_search where \

                                      searchid<(SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) \

                                        andsearchid>=$start AND searchid<=$end

           #sql_attr_uint和sql_attr_timestamp用於定義用於api過濾或者排序,寫多行制定多列

   sql_attr_uint        = typeid

   sql_attr_uint        = id

   sql_attr_timestamp   = adddate

           #分割槽查詢設定

   sql_query_range      = SELECTMIN(searchid),MAX(searchid) FROM v9_search

           #分割槽查詢的步長

   sql_range_step       = 1000

           #設定分割槽查詢的時間間隔

   sql_ranged_throttle  = 0

           #用於CLI的除錯

   sql_query_info       = SELECT *FROM v9_search WHERE searchid=$id

}

#定義一個增量的源

source search_main_delta : search_main

{

   sql_query_pre       = set namesutf8

           #增量源只查詢上次主索引生成後新增加的資料

#如果新增加的searchid比主索引建立時的searchid還小那麼會漏掉

   sql_query           = SELECTsearchid,typeid,id,adddate,data FROM v9_search where  \

                                  searchid>(SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) \

                                   andsearchid>=$start AND searchid<=$end

   sql_query_range     = SELECTMIN(searchid),MAX(searchid) FROM v9_search where \

                                       searchid>(SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )

}

#定義一個index_search_main索引

index index_search_main

{

           #設定索引的源

   source            = search_main

           #設定生成的索引存放路徑

   path         =/usr/local/coreseek/var/data/index_search_main

           #定義文件資訊的儲存模式,extern表示文件資訊和文件id分開儲存

   docinfo           = extern

           #設定已快取資料的記憶體鎖定,為0表示不鎖定

   mlock             = 0

           #設定詞形處理器列表,設定為none表示不使用任何詞形處理器

   morphology        = none

           #定義最小索引詞的長度

   min_word_len      = 1

           #設定字符集編碼型別,我這裡採用的utf8編碼和資料庫的一致

   charset_type      = zh_cn.utf-8

           #指定分詞讀取詞典檔案的位置

   charset_dictpath  =/usr/local/mmseg3/etc

           #不被搜尋的詞檔案裡表。

   stopwords       =/usr/local/coreseek/var/data/stopwords.txt

           #定義是否從輸入全文資料中取出HTML標記

   html_strip       = 0

}

#定義增量索引

index index_search_main_delta : index_search_main

{

   source   = search_main_delta

   path    =/usr/local/coreseek/var/data/index_search_main_delta

}

#定義indexer配置選項

indexer

{

           #定義生成索引過程使用索引的限制

   mem_limit        = 512M

}

#定義searchd守護程序的相關選項

searchd

{

           #定義監聽的IP和埠

   #listen            = 127.0.0.1

   #listen            =172.16.88.100:3312

    listen            = 3312

    listen            = /var/run/searchd.sock

           #定義log的位置

   log                =/usr/local/coreseek/var/log/searchd.log

           #定義查詢log的位置

   query_log          =/usr/local/coreseek/var/log/query.log

           #定義網路客戶端請求的讀超時時間

   read_timeout       = 5

           #定義子程序的最大數量

   max_children       = 300

           #設定searchd程序pid檔名

   pid_file           =/usr/local/coreseek/var/log/searchd.pid

           #定義守護程序在記憶體中為每個索引所保持並返回給客戶端的匹配數目的最大值

   max_matches        = 100000

           #啟用無縫seamless輪轉,防止searchd輪轉在需要預取大量資料的索引時停止響應

    #也就是說在任何時刻查詢都可用,或者使用舊索引,或者使用新索引

   seamless_rotate    = 1

           #配置在啟動時強制重新開啟所有索引檔案

   preopen_indexes    = 1

           #設定索引輪轉成功以後刪除以.old為副檔名的索引拷貝

   unlink_old         = 1

           # MVA更新池大小,這個引數不太明白

   mva_updates_pool   = 1M

           #最大允許的包大小

   max_packet_size    = 32M

           #最大允許的過濾器數

   max_filters        = 256

           #每個過濾器最大允許的值的個數

   max_filter_values  = 4096

}

綜合上面的資料,我對test.conf作了如下配置:

source message1
{
        type                    = mysql

        sql_host                = 127.0.0.1
        sql_user                = root
        sql_pass                = 123456
        sql_db                  = yh_comment
        sql_port                = 3308  # optional, default is 3306

        sql_query_pre           = SET NAMES utf8
        sql_query               = \
                SELECT id,bid,uid,content,valid,createtime \
                FROM tbl_cmt00 \
                UNION SELECT id,bid,uid,content,valid,createtime \
                FROM tbl_cmt01 \
                UNION SELECT id,bid,uid,content,valid,createtime \
                FROM tbl_cmt02 \
                UNION SELECT id,bid,uid,content,valid,createtime \
                FROM tbl_cmt03

        sql_field_string                = bid
        sql_attr_uint           = uid
        sql_field_string        = content
        sql_attr_string         = valid
        sql_field_string        = createtime
}


index message1
{
        source                  = message1
        path                    = /usr/local/sphinx/var/data/message1
        ngram_len               = 1 #表示使用一元字元切分模式,從而得以對單箇中文字元進行索引
        ngram_chars             = U+3000..U+2FA1F, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z, A..Z->a..z, a..z #表示要進行一元字元切分模式的字符集
}


indexer
{
        mem_limit               = 128M
}


searchd
{
        listen                  = 9412
        log                     = /usr/local/sphinx/var/log/searchd-message1.log
        query_log               = /usr/local/sphinx/var/log/query-message1.log
        read_timeout            = 5
        max_children            = 30
        pid_file                = /usr/local/sphinx/var/log/searchd-message1.pid
        #max_matches            = 1000
        seamless_rotate         = 1
        preopen_indexes         = 1
        unlink_old              = 1
        workers                 = threads # for RT to work
        binlog_path             = /usr/local/sphinx/var/data
}

上面的配置是已經開啟“一元切分模式”

具體可以參考文件http://www.coreseek.cn/products-install/ngram_len_cjk/

這樣配置就完成了,接下來要生成索引和開啟守護程序:

/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/test.conf --all

/usr/local/sphinx/bin/searchd -c /usr/local/sphinx/etc/test.conf

如果在建立索引的過程中出現”No fields in schema”的錯誤,原因是:sphinx對於sql資料來源需要至少一個sql_field_string,當沒有指定sql_field_string時會將資料來源中沒有明確指定為sql_attr_string的字串欄位用來做sql_field_string。當全部字串欄位設為sql_attr_string時不能建立索引,而隨便註釋一條sql_attr_string,或者選擇一條sql_attr_string變為sql_field_string,就可以了

如果資料庫更新了,需要重新建立索引,重輸一遍上面簡歷索引的指令就行

如果重建索引時守護程序正在執行,會報錯,需要執行下面的指令,會重建索引並且重開守護程序

/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/test.conf --all --rotate

現在進行php和sphinx的互動:

到http://pecl.php.net/package/sphinx下載php的sphinx模組,放到php中引用起來,方法不在此贅述

vim test.php

$sphinx = new SphinxClient;

//sphinx的主機名和埠

$sphinx->SetServer ( '192.168.1.168', 9412 );

$sphinx->SetConnectTimeout ( 1 );

//設定返回結果集為php陣列格式
$sphinx->SetArrayResult ( true );

//匹配結果的偏移量,引數的意義依次為:起始位置,返回結果條數,最大匹配條數

$sphinx->SetLimits(0, 20, 1000);

//最大搜索時間

$sphinx->SetMaxQueryTime(10);

//索引源是配置檔案中的 index 類,如果有多個索引源可使用,號隔開:'email,diary' 或者使用'*'號代表全部索引源

$index = 'message1';

//搜尋關鍵字

$result = $sphinx->Query ( '你要搜尋的非中文/中文字串', "*" );

if (!$result){
    print_r($sphinx->getLastError());
}

print_r($result);

$result是一個數組,其中

total是匹配到的資料總數量

matches是匹配的資料,包含id,attrs這些資訊

words是搜尋關鍵字的分詞

接下來介紹sphinx一些類似mysql條件的用法
//id的範圍
$sphinx->SetIdRange($min, $max);
 
//屬性過濾,可過濾的屬性必需在配置檔案中設定sql_attr_    ,之前我們定義了這些
 
    sql_attr_uint            = fromid
 
    sql_attr_uint            = toid
 
    sql_attr_timestamp  = sendtime
 
//如果你想再次修改這些屬性,配置完成後記得重新建立索引才能生效
 
 
 
//指定一些值
 
$sphinx->SetFilter('fromid', array(1,2));    //fromid的值只能是1或者2
 
//和以上條件相反,可增加第三個引數
 
$sphinx->SetFilter('fromid', array(1,2), false);    //fromid的值不能是1或者2
 
//指定一個值的範圍
 
$sphinx->SetFilterRange('toid', 5, 200);    //toid的值在5-200之間
 
//和以上條件相反,可增加第三個引數
 
$sphinx->SetFilterRange('toid', 5, 200, false);    //toid的值在5-200以外
 
 
 
//執行搜尋
 
$result = $sphinx->query('關鍵字', '*');

現在來講coreseek的安裝配置:

把包下載下來,我下載的地址是http://www.coreseek.cn/uploads/csft/3.2/coreseek-3.2.14.tar.gz

安裝過程可以參考官網文件http://www.coreseek.cn/products-install/install_on_bsd_linux/

我直接複製過來,照著打命令就可以了

##前提:需提前安裝作業系統基礎開發庫及mysql依賴庫以支援mysql資料來源和xml資料來源
##安裝mmseg
$ cd mmseg-3.2.14
$ ./bootstrap    #輸出的warning資訊可以忽略,如果出現error則需要解決
$ ./configure --prefix=/usr/local/mmseg3
$ make && make install
$ cd ..

##安裝coreseek
$ cd csft-3.2.14 或者 cd csft-4.0.1 或者 cd csft-4.1
$ sh buildconf.sh    #輸出的warning資訊可以忽略,如果出現error則需要解決
$ ./configure --prefix=/usr/local/coreseek  --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg3/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg3/lib/ --with-mysql    ##如果提示mysql問題,可以檢視MySQL資料來源安裝說明
$ make && make install
$ cd ..

這樣就算裝好了

接下來同樣是配置,和sphinx有些不一樣

同樣是參考官網文件http://www.coreseek.cn/products-install/coreseek_mmseg/

#以下部分為中文分詞核心配置
	#stopwords		= /path/to/stowords.txt的位置
	charset_dictpath		= /usr/local/mmseg3/etc/
	charset_type		= zh_cn.utf-8
	#charset_table                    = .................... #需將原有
的該配置註釋掉
	ngram_len                    = 0
#以上部分為中文分詞核心配置

關鍵在於:

#必須設定,表示詞典檔案的目錄,該目錄下必須有uni.lib詞典檔案存在

charset_dictpath=/usr/local/mmseg3/etc/

#必須設定,表示啟用中文分詞功能;否則中文分詞功能無效,使用sphinx的其他處理模式

charset_type=zh_cn.utf-8

#必須設定,表示取消原有的一元字元切分模式,不使其對中文分詞產生干擾

ngram_len=0

#charset_table的配置需要註釋掉!

#charset_table=......

我的配置是

source message1
{
        type                                    = mysql

        sql_host                                = 127.0.0.1
        sql_user                                = root
        sql_pass                                = 123456
        sql_db                                  = yh_comment
        sql_port                                = 3308  # optional, default is 3306

        sql_query_pre                           = SET NAMES utf8
        sql_query_pre                           = SET SESSION query_cache_type=OFF
        sql_query                               = \
                SELECT id,bid,uid,content,valid,createtime FROM tbl_cmt00

        sql_attr_uint                   = uid

        sql_query_info                  = SELECT * FROM tbl_cmt00 WHERE id=$id
}


index message1
{
        source                                  = message1
        path                                    = /usr/local/coreseek/var/data/message1
        docinfo                                 = extern
        charset_type            = zh_cn.utf-8
        ngram_len               = 0
        charset_dictpath    = /usr/local/mmseg3/etc/
}


indexer
{
        mem_limit                               = 32M
}


searchd
{
        port                                    = 9512
        log                                             = /usr/local/coreseek/var/log/searchd-message1.log
        query_log                               = /usr/local/coreseek/var/log/query-message1.log
        read_timeout                    = 5
        max_children                    = 30
        pid_file                                = /usr/local/coreseek/var/log/searchd-message1.pid
        max_matches                             = 1000
        seamless_rotate                 = 1
        preopen_indexes                 = 0
        unlink_old                              = 1
}

現在可以嘗試搜尋

/usr/local/coreseek/bin/search -c /usr/local/coreseek/etc/test.conf 你要搜尋的非中文/中文字串

結果應該是類似:

displaying matches:
1. document=4, weight=5, uid=3046690
        id=4
        bid=3046730-4e842acdcf8be
        uid=3046690
        content=??????????
        valid=y
        createtime=1317286728

words:
1. '沒有': 683 documents, 700 hits
2. '聽': 124 documents, 134 hits
3. '過': 722 documents, 741 hits
4. ',': 9797 documents, 11936 hits
5. '過來': 47 documents, 47 hits
6. '一下': 404 documents, 404 hits

coreseek和php的互動

總的來說和sphinx的互動幾乎是一樣的

用的是pecl的sphinx模組的話,可能$result會返回false,使用getLastError()方法會返回

client version is higher than daemon version
這樣的錯誤

可以禁用pecl的sphinx模組,轉而使用coreseek包中提供的sphinxapi.php

ls /usr/local/coreseek/api/*.php

sphinxapi.php
test2.php
test_coreseek.php
test.php

test*.php都是demo,可以作為參考

自己寫個test.php

vim test.php

include './sphinxapi.php';

$sphinx->SetServer ( '192.168.1.168', 9512 );
$sphinx->SetArrayResult ( true );

$index = 'message1';

$result = $sphinx->Query ( '搜尋關鍵字', "*" );

if (!$result){
    print_r($sphinx->getLastError());
}

print_r($result);

其他的和sphinx一樣

結束!