??最近一個(gè)項(xiàng)目需要實(shí)現(xiàn)這樣一個(gè)需求:mysql數(shù)據(jù)庫(kù)一張表中存了百萬(wàn)張菜品圖片,需要根據(jù)菜品名稱或描述,模糊匹配出符合條件的菜品圖片,并展示出來
select * from table_name where column like '%魚香肉絲%';
??如果像上面那樣,直接使用mysql like查詢的話,會(huì)進(jìn)行全表掃描,不走索引,大大的影響查詢效率,所以開始學(xué)習(xí)使用Sphinx全文搜索引擎,下面記錄下第一次配置使用的過程,以及過程中遇到的問題和疑問,望指正.
1. 下載sphinx源碼壓縮包點(diǎn)擊下載
按照自己的需求,下載對(duì)應(yīng)的版本,我這里下載的是Windows x64 binaries 3.1.1 版本
2. 下載后的sphinx源碼目錄
3.配置文件
打開etc目錄,里面有三個(gè)文件,example,sql是創(chuàng)建測(cè)試表的腳本,我們稍后會(huì)用到,sphinx.conf.dist是完整版默認(rèn)配置,這里我選擇了sphinx-min.conf.dist簡(jiǎn)化版,暫時(shí)可以滿足需求,復(fù)制一份到bin目錄下,并且重命名為sphinx.conf.
4. sphinx.config文件配置
配置文件的幾個(gè)組成部分:
- source 數(shù)據(jù)源,這里配置你要進(jìn)行全文檢索的數(shù)據(jù)的來源
- index 索引,從上面的數(shù)據(jù)源處構(gòu)建索引,相當(dāng)于字典檢索,要有整本字典內(nèi)容后才會(huì)有索引
- indexer 構(gòu)建索引,需要重新構(gòu)建索引時(shí),其實(shí)就是調(diào)用indexer這個(gè)命令
- searchd 提供搜索查詢的服務(wù),后臺(tái)運(yùn)行
source src1 ## src1為數(shù)據(jù)源命名的名稱,可以根據(jù)數(shù)據(jù)源的屬性更改
{
type = mysql ## 數(shù)據(jù)源,本項(xiàng)目使用mysql
sql_host = localhost ## 數(shù)據(jù)庫(kù)服務(wù)器,這里因?yàn)槭菧y(cè)試,使用的是本地?cái)?shù)據(jù)庫(kù)
sql_user = root # 數(shù)據(jù)庫(kù)用戶名
sql_pass = root # 數(shù)據(jù)庫(kù)密碼
sql_db = hongbao ## 數(shù)據(jù)庫(kù)名稱,替換成你自己的數(shù)據(jù)庫(kù)名稱
sql_port = 3306 ## 數(shù)據(jù)庫(kù)端口,默認(rèn)3306
sql_query_pre = SET NAMES utf8 ## 如果你的數(shù)據(jù)庫(kù)不是uft8編碼的,注釋掉本行
sql_query = \ ## 主查詢,查詢出所有在檢索范圍的數(shù)據(jù)
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 ## 屬性,可用來排序
}
index test1 ## 索引名稱,自行命名
{
source = src1 ## 基于這個(gè)數(shù)據(jù)源構(gòu)建索引
path = D:/sphinx/data/ ## 存放索引的目錄,自己創(chuàng)建
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F ## 指定utf-8的編碼表
mlock = 0
morphology = none ## 詞形處理器,如果檢索中文用不到,dogs<==>dog
min_word_len = 1 ## 最小索引詞長(zhǎng)度,小于這個(gè)長(zhǎng)度的詞不會(huì)被索引
ngram_len = 1 ## 簡(jiǎn)單分詞,只支持0和1,如果要搜索中文,請(qǐng)指定為1
ngram_chars = U+3000..U+2FA1F ## 需要分詞的字符,如果要搜索中文,請(qǐng)放開這行
html_strip = 0 ## html標(biāo)記清理,是否從輸出全文數(shù)據(jù)中去除HTML標(biāo)記
}
indexer
{
# memory limit, in bytes, kiloytes (16384K) or megabytes (256M)
# optional, default is 128M, max is 2047M, recommended is 256M to 1024M
mem_limit = 128M ## 建立索引的時(shí)候,索引內(nèi)存限制
}
searchd
{
listen = 9312 ## 監(jiān)聽端口
listen = 9306:mysql41
log = D:/sphinx/log/searchd.log ## 監(jiān)聽日志
query_log = D:/sphinx/log/query.log ## 查詢?nèi)罩? pid_file = D:/sphinx/log/searchd.pid ## ## 進(jìn)程id文件
read_timeout = 5 ## 客戶端讀超時(shí)時(shí)間
client_timeout = 300 ## 客戶端持久連接超時(shí)時(shí)間,即客戶端讀一次以后,持久連接,然后再讀一次,中間這個(gè)持久連接的時(shí)間
max_children = 30 ## 并行執(zhí)行搜索的數(shù)目
persistent_connections_limit = 30
preopen_indexes = 1 ## 索引預(yù)開啟返顺,是否強(qiáng)制重新打開所有索引文件
unlink_old = 1 ## 索引輪換成功之后总寒,是否刪除以.old為擴(kuò)展名的索引拷貝
max_packet_size = 8M ## 網(wǎng)絡(luò)通訊時(shí)允許的最大的包的大小
max_filters = 256 ## 每次查詢?cè)试S設(shè)置的過濾器的最大個(gè)數(shù)
max_filter_values = 4096 ## 單個(gè)過濾器允許的值的最大個(gè)數(shù)
max_batch_queries = 32 ## 每次批量查詢的查詢數(shù)限制
workers = threads # for RT to work 多處理模式(MPM)。 可選項(xiàng)凝化;可用值為none宠进、fork渊抽、prefork建蹄,以及threads帆阳。 默認(rèn)在Unix類系統(tǒng)為form,Windows系統(tǒng)為threads氨距。
}
注:配置文件更改完成之后,回到根目錄新建配置文件中使用到的data和log兩個(gè)目錄
導(dǎo)入源碼里提供的示例數(shù)據(jù),執(zhí)行etc目錄下的example.sql腳本:
或者使用mysql圖形處理界面工具:
5. 根據(jù)sphinx.conf創(chuàng)建索引
## 構(gòu)建索引語(yǔ)法:
indexer -c 配置文件 索引名字
- 打開windows 命令提示行工具,進(jìn)入到sphinx/bin目錄下
- 啟動(dòng)sphinx檢索服務(wù),后臺(tái)常駐
- 查看索引創(chuàng)建情況
重新打開一個(gè)命令行窗口,
6. Sphinxapi.php使用(或者安裝php擴(kuò)展)
sphinx提供了各種語(yǔ)言的代碼,php使用sphinx,只需要引入sphinxapi.php,打開根目錄下的api目錄,將sphinxapi.php文件復(fù)制到你的項(xiàng)目目錄下,方便調(diào)用
<?php
/**
* Demo.php
* Create on 2018/8/29 10:42
* Create by liu
* Administrator
*/
class Demo extends CI_Controller
{
private $sphinx;
public function __construct()
{
parent::__construct();
require_once APPPATH . 'libraries/Sphinxapi.php';
$this->sphinx = new SphinxClient();
}
public function sphinx()
{
//設(shè)置操作哪個(gè)sphinx服務(wù)器
$this->sphinx->setServer('localhost',9312);
$keyword = "銀行";//要搜索的關(guān)鍵字
$index = 'bank';//索引名稱
//查詢出關(guān)鍵字所在的主鍵id
$this->sphinx->_limit = 2000;
$res = $this->sphinx->Query($keyword,$index);
echo '<pre>';
if (isset($res['matches'])){
$ids = array_keys($res['matches']);
$ids = implode(',',$ids);
}else{
print_r("內(nèi)容不存在");
return;
}
//獲取匹配到的主鍵id
$mysql_con = mysqli_connect('localhost','root','','hongbao');//本地?cái)?shù)據(jù)庫(kù)
mysqli_query($mysql_con,'set name utf8');
mysqli_query($mysql_con,'use hongbao');
$sql = "select * from bank where id in ($ids)";
$res = mysqli_query($mysql_con,$sql);
while ($row = mysqli_fetch_assoc($res)){
$data[] = $row;
}
foreach ($data as $key => $v){
$v = str_replace($keyword,"<font color='red'>{$keyword}</font>",$v);
$data[$key] = $v;
}
print_r($data);
}
}
代碼運(yùn)行結(jié)果