PHP+Mysql+Sphinx高效的站內搜尋引擎搭建詳釋
假設你現在運營著一個論壇,論壇資料已經超過100W,很多使用者都反映論壇搜尋的速度非常慢,那麼這時你就可以考慮使用Sphinx了(當然其他的全文檢索程式或方法也行)。
Sphinx是什麼
Sphinx由俄羅斯人Andrew Aksyonoff 開發的高效能全文搜尋軟體包,在GPL與商業協議雙許可協議下發行。
全文檢索是指以文件的全部文字資訊作為檢索物件的一種資訊檢索技術。檢索的物件有可能是文章的標題,也有可能是文章的作者,也有可能是文章摘要或內容。
Sphinx的特性
高速索引 (在新款CPU上,近10 MB/秒);高速搜尋 (2-4G的文字量中平均查詢速度不到0.1秒);高可用性 (單CPU上最大可支援100 GB的文字,100M文件); 提供良好的相關性排名;支援分散式搜尋; 提供文件摘要生成; 提供從MySQL內部的外掛式儲存引擎上搜索 ; 支援布林,短語, 和近義詞查詢; 支援每個文件多個全文檢索域(預設最大32個); 支援每個文件多屬性; 支援斷詞; 支援單位元組編碼與UTF-8編碼;
下載並安裝Sphinx
開啟網址http://www.coreseek.cn/news/7/52/ 找到適合自己的作業系統的版本,比如我是Windows那麼我就可以下載Coreseek Win32通用版本,Linux下可以下載原始碼包,自己編譯安裝。這裡解釋下為什麼我們下載的程式叫Coreseek,Coreseek是基於Sphinx開發的一款軟體,對Sphinx做了一些改動,在中文方面支援得比Sphinx好,所以我們使用之。
下載完成後,將程式解壓到你想解壓的地方,比如我就想解壓到E盤根目錄,之後修改目錄名為Coreseek,大功告成Coreseek安裝完成了,安裝的目錄是在E:\coreseek\。
使用Sphinx
我要使用Sphinx需要做以下幾件事
1)、首先得有資料
2)、建立Sphinx配置檔案
3)、生成索引
4)、啟動Sphinx
5)、使用之(呼叫api或search.exe程式進行查詢)
第1步:(匯入資料)
我們建立測試所需要用到得資料庫、表以及資料,篇幅有限,這些在附件中都有,下載後匯入MySQL即可。
第2步:(建立配置檔案)
接下來我們需要建立一個Sphinx的配置檔案 E:\coreseek\etc\mysql.conf,將其內容改為下面這些:
source mysql
{type = mysql //資料庫型別sql_host = localhost //資料庫地址sql_user = root //資料庫使用者名稱sql_pass = //資料庫密碼sql_db = test //資料庫名sql_port = 3306 //埠號sql_query_pre = SET NAMES utf8 //設定字符集sql_query = SELECT id,addtime,title,content FROM postsql_attr_timestamp = addtime}index mysql{source = mysqlpath = E:/coreseek/var/data/mysqlcharset_dictpath = E:/coreseek/etc/charset_type = zh_cn.utf-8}
searchd{listen = 9312max_matches = 1000pid_file = E:/coreseek/var/log/searchd_mysql.pidlog = E:/coreseek/var/log/searchd_mysql.logquery_log = E:/coreseek/var/log/query_mysql.log}
先講下這個配置檔案中每項的含義。
source mysql{} 定義源名稱為mysql,也可以叫其他的,比如:source xxx{}type 資料來源型別 。
sql_* 資料相關的配置,比如sql_host,sql_pass什麼的,這些不解釋。
sql_query 建立索引時的查詢命令,在這裡儘可能不使用where或group by,將where與groupby的內容交給sphinx,由sphinx進行條件過濾與groupby效率會更高,注意:select 的欄位必須包括一個唯一主鍵以及要全文檢索的欄位,where中要用到的欄位也要select出來
sql_query_pre 在執行sql_query前執行的sql命令, 可以有多條。
sql_attr 以這個開頭的配置項,表示屬性欄位,在where,orderby,groupby中出現的欄位要分別定義一個屬性,定義不同型別的欄位要用不同的屬性名,比如上面的sql_attr_timestamp就是時間戳型別。
index mysql{} 定義索引名稱為mysql,也可以叫其他的,比如:index xxx{}
source 關聯源,就是source xxx定義的。
path 索引檔案存放路徑,比如:E:/coreseek/var/data/mysql 實際存放在E:/coreseek/var/data/目錄,然後建立多個名稱為mysql字尾卻不同的索引檔案
charset_dictpath 指明分詞法讀取詞典檔案的位置,當啟用分詞法時,為必填項。在使用LibMMSeg作為分詞 庫時,需要確保詞典檔案uni.lib在指定的目錄下
charset_type 字符集,比如charset_type = zh_cn.gbk
searchd{} sphinx守護程序配置
listen 監聽埠
max_matches最大匹配數,也就是查詢的資料再多也只返回這裡設定的1000條
pid_file pid檔案路徑
log全文檢索日誌
query_log查詢日誌
好了,配置檔案就這樣,配置的引數還有很多,大家可以自己查文件。
第3步:(生成索引)
開始 -> 執行 -> 輸入cmd回車,開啟命令列工具
e:\coreseek\bin\indexer –config e:\coreseek\etc\mysql.conf –all
這一串東西其實就是呼叫indexer程式來生成所有索引
如果只想對某個資料來源進行索引,則可以這樣:
e:\coreseek\bin\indexer –config e:\coreseek\etc\mysql.conf 索引名稱(索引名稱指配置檔案中所定義的)
–config,–all這些都是indexer程式的引數,想了解更多引數的朋友可以檢視文件
執行命令後如果你沒看到FATAL,ERROR這些東西,那麼索引檔案就算生成成功了,比如我看到得就是
………省略………using config file ‘e:\coreseek\etc\mysql.conf’…indexing index ‘mysql’…collected 4 docs, 0.0 MB………省略………
第4步:(啟動Sphinx)
同樣命令列下 :
e:\coreseek\bin\searchd –config e:\coreseek\etc\mysql.conf
執行後提示了一大堆東西
…省略…
using config file ‘e:\coreseek\etc\mysql.conf’…listening on all interfaces, port=9312accepting connections
不用管這些鳥文是啥意思,反正Sphinx是啟動好了。
現在有一串鳥文的這個命令列是不能關的,因為關了Sphinx也就關了,如果覺得這樣不爽,可以將Sphinx安裝成系統服務,在後臺執行,安裝系統服務只需在命令列中輸入以下命令:
e:\coreseek\bin\searchd –config e:\coreseek\etc\mysql.conf –install安裝之後記得啟動這個服務,不會啟動那我沒法,自己google。
第5步:(使用Sphinx)
在web根目錄下建立一個search目錄(當然不在根目錄也行,同樣目錄名也可以隨取),複製E:\coreseek\api\ sphinxapi.php檔案到search目錄(sphinxapi.php這個是sphinx官方提供的api),開始php程式的編寫。
在search目錄建立一個檔案,名字叫啥都行,我管它叫index.php,其內容如下
<?phpinclude ‘sphinxapi.php’; // 載入Sphinx API$sc = new SphinxClient(); // 例項化Api$sc->setServer(‘localhost’, 9312); // 設定服務端,第一個引數sphinx伺服器地址,第二個sphinx監聽埠
$res = $sc->query(‘sphinx’, ‘mysql’); // 執行查詢,第一個引數查詢的關鍵字,第二個查詢的索引名稱,mysql索引名稱(這個也是在配置檔案中定義的),多個索引名稱以,分開,也可以用*表示所有索引。
print_r($res);
列印結果:
Array (………省略………[matches] => Array([2] => Array([weight] => 2[attrs] => Array([addtime] => 1282622004))[4] => Array([weight] => 2[attrs] => Array([addtime] => 1282622079)))………省略………)
Matches中就是查詢的結果了,但是彷彿不是我們想要的資料,比如titile,content欄位的內容就沒有查詢出來,根據官方的說明是Sphinx並沒有連線到MySQL去取資料,只是根據它自己的索引內容進行計算,因此如果想用Sphinx提供的API去取得我們想要的資料,還必須以查詢的結果為依據,再次查詢MySQL從而得到我們想要的資料。
查詢結果中鍵值分別表示2唯一主鍵weight權重attrs sql_attr_*中配置至此,搜尋引擎算是完成一大半了,剩下的大家可以自行完成。
比如:<?php$ids = array_keys($res['matches']); // 獲取主鍵$ids = join(‘,’, $ids);$query = mysql_query(“SELECT * FROM post WHERE id IN ({$ids})”);
while($row = mysql_fetch_assoc($query)) {…..}
Sphinx在windows下安裝使用
前一陣子嘗試使用了一下Sphinx,一個能夠被各種語言(PHP/Python/Ruby/etc)方便呼叫的全文檢索系統。網上的資料大多是在 linux環境下的安裝使用,當然,作為生產環境很有必要部署在*nix環境下,作為學習測試,還是windows環境比較方便些。
本文旨在提供一種便捷的方式讓Sphinx在windows下安裝配置以支援中文全文檢索,配置部分在linux下通用。
一、關於Sphinx
Sphinx 是一個在GPLv2 下發布的一個全文檢索引擎,商業授權(例如, 嵌入到其他程式中)需要聯絡作者(Sphinxsearch.com)以獲得商業授權。
一般而言,Sphinx是一個獨立的搜尋引擎,意圖為其他應用提供高速、低空間佔用、高結果相關度的全文搜尋功能。Sphinx可以非常容易的與 SQL資料庫和指令碼語言整合。
當前系統內建MySQL和PostgreSQL 資料庫資料來源的支援,也支援從標準輸入讀取特定格式的XML資料。通過修改原始碼,使用者可以自行增加新的資料來源(例如:其他型別的DBMS的原生支援)。
搜尋API支援PHP、Python、Perl、Rudy和Java,並且也可以用作MySQL儲存引擎。搜尋API非常簡單,可以在若干個小時之 內移植到新的語言上。
中文手冊可以在這裡獲得(酷勤 網備用下載地址:sphinx_doc_zhcn_0.9.pdf)。
二、Sphinx在windows上的安裝
1.直接在http://www.sphinxsearch.com/downloads.html找 到最新的windows版本,我這裡下的是Win32 release binaries with MySQL support,下載後解壓在D:\sphinx目錄下;
2.在D:\sphinx\下新建一個data目錄用來存放索引檔案, 一個log目錄方日誌檔案,複製D:\sphinx\sphinx.conf.in到D:\sphinx\bin\sphinx.conf(注意修改檔案 名);
3.修改D:\sphinx\bin\sphinx.conf,我這裡 列出需要修改的幾個:
type = mysql # 資料來源,我這裡是
mysql
sql_host = localhost # 資料庫伺服器
sql_user = root # 資料庫使用者名稱
sql_pass = '' # 資料庫密碼
sql_db = test # 資料庫
sql_port = 3306 # 資料庫埠
sql_query_pre = SET NAMES utf8 # 去掉此行前面的註釋,如果你的資料庫是uft8編碼的
index test1
{
# 放索引的目錄
path = D:/sphinx/data/
# 編碼
charset_type = utf-8
# 指定utf-8的編碼表
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
# 簡單分詞,只支援0和1,如果要搜尋中文,請指定為1
ngram_len = 1
# 需要分詞的字元,如果要搜尋中文,去掉前面的註釋
ngram_chars = U+3000..U+2FA1F
}
# index test1stemmed : test1
# {
# path = @
# morphology = stem_en
# }
# 如果沒有分散式索引,註釋掉下面的內容
# index dist1
# {
# 'distributed' index type MUST be specified
# type = distributed# local index to be searched
# there can be many local indexes configured
# local = test1
# local = test1stemmed
# remote agent
# multiple remote agents may be specified
# syntax is 'hostname:port:index1,[index2[,...]]
# agent = localhost:3313:remote1
# agent = localhost:3314:remote2,remote3
# remote agent connection timeout, milliseconds
# optional, default is 1000 ms, ie. 1 sec
# agent_connect_timeout = 1000
# remote agent query timeout, milliseconds
# optional, default is 3000 ms, ie. 3 sec
# agent_query_timeout = 3000
# }
# 搜尋服務需要修改的部分
searchd
{
# 日誌
log = D:/sphinx/log/searchd.log
# PID file, searchd process ID file name
pid_file = D:/sphinx/log/searchd.pid# windows下啟動searchd服務一定要註釋掉這個
# seamless_rotate = 1
}
4.匯入測試資料
sql 檔案在D:/sphinx/example.sql
C:\Program Files\MySQL\MySQL Server 5.0\bin>mysql -uroot test<d:/sphinx/example.sql
5.建立索引
D:\sphinx\bin>indexer.exe test1 (備註:test1為 sphinx.conf 的 index test1() )Sphinx 0.9.8-release (r1533)Copyright (c) 2001-2008, Andrew Aksyonoff
using config file ‘./sphinx.conf’…indexing index ‘test1′…collected 4 docs, 0.0 MBsorted 0.0 Mhits, 100.0% donetotal 4 docs, 193 bytestotal 0.101 sec, 1916.30 bytes/sec, 39.72 docs/sec
D:\sphinx\bin>
6.搜尋’test’試試
D:\sphinx\bin>search.exe test1Sphinx 0.9.8-release (r1533)Copyright (c) 2001-2008, Andrew Aksyonoff
using config file ‘./sphinx.conf’…index ‘test1′: query ‘test ‘: returned 3 matches of 3 total in 0.000 sec
displaying matches:1. document=1, weight=2, group_id=1, date_added=Wed Nov 26 14:58:59 2008id=1group_id=1group_id2=5date_added=2008-11-26 14:58:59title=test onecontent=this is my test document number one. also checking search withinphrases.2. document=2, weight=2, group_id=1, date_added=Wed Nov 26 14:58:59 2008id=2group_id=1group_id2=6date_added=2008-11-26 14:58:59title=test twocontent=this is my test document number two3. document=4, weight=1, group_id=2, date_added=Wed Nov 26 14:58:59 2008id=4group_id=2group_id2=8date_added=2008-11-26 14:58:59title=doc number fourcontent=this is to test groups
words:1. ‘test’: 3 documents, 5 hitsD:\sphinx\bin>
都所出來了吧。
6.測試中文搜尋
修改test資料庫中documents資料表,
UPDATE `test`.`documents` SET `title` = ‘測試中文’, `content` = ‘this is my test document number two,應該搜的到吧’ WHERE `documents`.`id` = 2;
重建索引:
D:\sphinx\bin>indexer.exe test1
搜尋’中文’試試:
D:\sphinx\bin>search.exe 中文Sphinx 0.9.8-release (r1533)Copyright (c) 2001-2008, Andrew Aksyonoff
using config file ‘./sphinx.conf’…index ‘test1′: query ‘中文 ‘: returned 0 matches of 0 total in 0.000 sec
words:D:\sphinx\bin>
貌似沒有搜到,這是因為windows命令列中的編碼是gbk,當然搜不出來。我們可以用程式試試,在D:\sphinx\api下新建一個 foo.php的檔案,注意utf-8編碼
<?phprequire ’sphinxapi.php’;$s = new SphinxClient();$s->SetServer(’localhost’,9312);$result = $s->Query(’中文’);var_dump($result);?>
啟動Sphinx searchd服務
D:\sphinx\bin>searchd.exeSphinx 0.9.8-release (r1533)Copyright (c) 2001-2008, Andrew Aksyonoff
WARNING: forcing –console mode on Windowsusing config file ‘./sphinx.conf’…creating server socket on 0.0.0.0:9312accepting connections
已經表示伺服器已經開啟 不要關閉 命令列 (目前本人無法將此服務安裝成系統伺服器 所以每次PHP測試前注意開啟 searchd 服務)
執行PHP查詢:
訪問 http://www.wszwl.com/sphinx/api/foo.php (自己配置的虛擬主機)
結果是不是出來?剩下的工作就是去看手冊,慢慢摸索高階的配置。
Windows下的Sphinx+MySQL簡單配置及除錯
2010年01月15日 星期五 02:44 P.M.
首先我們要從 Sphinx 官網上 http://www.sphinxsearch.com/downloads.html 下載mysql-5.0.45-sphinxse-0.9.8-win32.zip 和 sphinx-0.9.8.1-win32.zip,假設你已經安裝好了 MySQL
先將 mysql 服務停掉 解壓 mysql-5.0.45-sphinxse-0.9.8-win32.zip 將 bin 和share 覆蓋掉 mysql 目錄中的 bin 和 share 解壓 sphinx-0.9.8.1-win32.zip 到獨立的目錄,如:d:/www/sphinx/中接著開啟 mysql 服務,建立 “test” 資料庫,並匯入 sql 語句,如下:
———————————————————–
CREATE TABLE `documents` (`id` int(11) NOT NULL auto_increment,`group_id` int(11) NOT NULL,`group_id2` int(11) NOT NULL,`date_added` datetime NOT NULL,`title` varchar(255) NOT NULL,`content` text NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=5;
INSERT INTO `documents` VALUES (’1′, ’1′, ’5′, ’2008-09-13 21:37:47′, ‘test one’, ‘this is my test document number one. also checking search within phrases.’);INSERT INTO `documents` VALUES (’2′, ’1′, ’6′, ’2008-09-13 21:37:47′, ‘test two’, ‘this is my test document number two’);INSERT INTO `documents` VALUES (’3′, ’2′, ’7′, ’2008-09-13 21:37:47′, ‘another doc’, ‘this is another group’);INSERT INTO `documents` VALUES (’4′, ’2′, ’8′, ’2008-09-13 21:37:47′, ‘doc number four’, ‘this is to test groups’);
——————————————-實際上,這個新建立的表就是 Sphinx 中的 example.sql
我們的測試表已經建立完成,接下來我們要配置 sphinx-doc.conf 檔案(重要)
先將 sphinx 下的 sphinx-min.conf 複製一份改名為 sphinx-doc.conf,接著 修改它:
# Minimal Sphinx configuration sample (clean, simple, functional)## type——————資料庫型別,目前支援 mysql 與 pgsql# strip_html————是否去掉html 標籤# sql_host————–資料庫主機地址# sql_user————-資料庫使用者名稱# sql_pass————-資料庫密碼# sql_db————–資料庫名稱# sql_port————-資料庫採用的埠# sql_query_pre——–執行sql前要設定的字符集,用utf8必須SET NAMES utf8# sql_query———–全文檢索要顯示的內容,在這裡儘可能不使用where或 group by,將 where 與 groupby 的內容交給 sphinx,由 sphinx 進行條件過濾與 groupby 效率會更高# 注意: select 出來的欄位必須至少包括一個唯一主鍵 (ARTICLESID) 以及要全文檢索的欄位,你計劃原本在 where 中要用到的欄位也要 select 出來# 這裡不用使用orderby# sql_attr_ 開頭的表示一些屬性欄位,你原計劃要用在 where, orderby, groupby 中的欄位要在這裡定義(# 為自己新增的註釋內容)
#source 資料來源名:
source documents{type = mysqlsql_host = localhostsql_user = rootsql_pass = yourpasswordsql_db = testsql_port = 3306 # optional, default is 3306
sql_query_pre = SET NAMES utf8sql_query = \SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \FROM documents
sql_attr_uint = group_idsql_attr_timestamp = date_added
sql_query_info = SELECT * FROM documents WHERE id=$id}
index documents{source = documents
#path 索引記錄存放目錄,如 d:/sphinx/data/cgfinal ,實際存放時會存放在d:/sphinx/data目錄,然後建立多個 cgfinal名稱,不同副檔名的索引檔案。path = d:/www/sphinx/data/docdocinfo = externenable_star = 1
min_word_len = 3min_prefix_len = 0min_infix_len = 3charset_type = sbcs
# 其他的配置如 min_word_len, charset_type, charset_table, ngrams_chars, ngram_len 這些則是支援中文檢索需要設定的內容。# 如果檢索的不是中文,則 charset_table, ngrams_chars, min_word_len 就要設定不同的內容,具體官方網站的論壇中有很多,大家可以去搜索看看。}
# mem_limit 索引使用記憶體最大限制,根據機器情況而定,預設是32M,太小的會影響索引的效能。indexer{mem_limit = 32M}
# 搜尋的守護程序配置# 在進行全文檢索過程中,searchd要先開啟,mysql在全文檢索時才能連線到sphinx,由sphinx進行全文檢索,再將結果返回給mysql# address 偵聽請求的地址,不設定則偵聽所有地址# port 偵聽埠searchd{port = 3312log =d:/www/sphinx/logs/searched_doc.logquery_log = d:/www/sphinx/logs/query_doc.logread_timeout = 5max_children = 30pid_file = d:/www/sphinx/logs/searched-doc.pidmax_matches = 1000seamless_rotate = 0preopen_indexes = 0unlink_old = 1}
為了測試,我們的 Sphinx 配置檔案已經寫好,確保我們的 Mysql 資料庫已經啟動,如果沒有啟動則在 cmd 中鍵入” net start mysql “
接下來,我們的測試正式開始:
1,生成資料索引或重建索引:
(最好再複製一個 sphinx-doc.conf 配置檔案,並把它放入 bin 資料夾中,下面的舉例 假設我們已經這樣做):
在 cmd 模式下:輸入:
d:/www/sphinx/bin/indexer.exe –config d:/www/sphinx/bin/sphinx-doc.conf documents
2,執行檢索守護程序 searchd.exe:
d:/www/sphinx/bin/searchd.exe –config d:/www/sphinx/bin/sphinx-doc.conf
如過這兩步沒有報錯的話,說明我們的 Sphinx 已經正常運行了!可以通過 netstat -an檢視是否 3312 埠是否處如監聽狀態。
3,現在來用 sphinx 自帶的工具 search.exe 來測試一下:
測試:
索引關鍵字: this is m
D:\www\sphinx\bin>search.exe -c d:/www/sphinx/bin/sphinx-doc.conf this is m
結果:
Sphinx 0.9.8-release (r1371)Copyright (c) 2001-2008, Andrew Aksyonoff
using config file ‘d:/www/sphinx/bin/sphinx-doc.conf’…WARNING: index ‘documents’: invalid morphology option ‘extern’ – IGNOREDindex ‘documents’: query ‘this is m ‘: returned 4 matches of 4 total in 0.000 sc
displaying matches:1. document=1, weight=1, group_id=1, date_added=Sat Sep 13 21:37:47 2008id=1group_id=1group_id2=5date_added=2008-09-13 21:37:47title=test onecontent=this is my test document number one. also checking search withiphrases.2. document=2, weight=1, group_id=1, date_added=Sat Sep 13 21:37:47 2008id=2group_id=1group_id2=6date_added=2008-09-13 21:37:47title=test twocontent=this is my test document number two3. document=3, weight=1, group_id=2, date_added=Sat Sep 13 21:37:47 2008id=3group_id=2group_id2=7date_added=2008-09-13 21:37:47title=another doccontent=this is another group4. document=4, weight=1, group_id=2, date_added=Sat Sep 13 21:37:47 2008id=4group_id=2group_id2=8date_added=2008-09-13 21:37:47title=doc number fourcontent=this is to test groups
words:1. ‘this’: 4 documents, 4 hits
——————-
索引關鍵字: this is another group
D:\www\sphinx\bin>search.exe -c d:/www/sphinx/bin/sphinx-doc.conf this is another group
結果:
Sphinx 0.9.8-release (r1371)Copyright (c) 2001-2008, Andrew Aksyonoff
——–
到此sphinx在win上算正常運行了,sphinx-doc.conf檔案配置比較靈活,根據你需要索引的資料庫進行靈活配置來達到你需要的效果
如果配置過程中出現執行引數配置問題可以檢視 doc/sphinx.html檔案,裡面對各種引數都要詳細的說明
using config file ‘d:/www/sphinx/bin/sphinx-doc.conf’…WARNING: index ‘documents’: invalid morphology option ‘extern’ – IGNOREDindex ‘documents’: query ‘this is another group ‘: returned 1 matches of 1 totalin 0.000 sec
displaying matches:1. document=3, weight=4, group_id=2, date_added=Sat Sep 13 21:37:47 2008id=3group_id=2group_id2=7date_added=2008-09-13 21:37:47title=another doccontent=this is another group
words:1. ‘this’: 4 documents, 4 hits2. ‘another’: 1 documents, 2 hits3. ‘group’: 1 documents, 1 hits