最近比较忙,今天抽空完善了一下。

What/Sphinx是什么?
定义:Sphinx是一个全文检索引擎。

Why/为什么使用Sphinx?
遇到一个类似这样的需求:用户可以通过文章标题和文章搜索到一片文章的内容,而文章的标题和文章的内容分别保存在不同的库,而且是跨机房的这种类似的例子。
sphinx 官网下载地址(这里根据自己的情况选择相应的版本下载即可)
这里我下载的是sphinx-3.1.1-release-win64.zip,将下载的文件解压,解压后将文件夹重命名为sphinx(方便后续操作,目录结构如下图所示) sphinx 目录结构
1.png

1.png

如果没有data和log目录自己创建一下即可。 将上一步得到的sphinx文件夹剪切或复制到某个磁盘下,这里我放到E:\PRO\2\下 将E:\PRO\2\sphinx\etc\sphinx-min.conf.dist复制到E:\PRO\2\sphinx\bin\下,并重命名为sphinx.conf; 修改E:\PRO\2\sphinx\bin\sphinx.conf文件的数据库配置,这里根据自己的情况进行配置即可(如下图) bin 目录

2.png

2.png

Minimal Sphinx configuration sample (clean, simple, functional)

主索引数据原定义

source article_main { type = mysql #数据库类型 sql_host = localhost #数据库地址 sql_user = root #用户名 sql_pass = 123456 #密码 sql_db = test #数据库名 sql_port = 3306 #端口 sql_query_pre = SET NAMES utf8 #编码 sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM sphinx_article #获取数据源表最大的主键id 插入到sph_counter表做标记 #使用多次查询,那么这个多次查询就需要有个范围和步长,sql_query_range和sql_range_step就是做这个使用的。 sql_query_range = sql_range_step = 10000 sql_query = SELECT * FROM sphinx_article WHERE id <= (SELECT max_doc_id FROM sph_counter WHERE counter_id = 1) #sql_attr_uint = cat_id #sql_attr_uint = member_id sql_attr_timestamp = created #从SQL读取到的值必须为整数,作为时间属性 #sql_query_info_pre = SET NAMES utf8 #命令行查询时,设置正确的字符集 #sql_query_post = SELECT * FROM sphinx_article WHERE id=$id #命令行查询时,从数据库读取原始数据信息 } # 增量索引数据原定义 source article_delta :article_main { sql_query_pre = SET NAMES utf8 sql_query_range = sql_range_step = 10000 sql_query = select * from sphinx_article where id > (select max_doc_id from sph_counter where counter_id = 1) sql_attr_timestamp = created sql_query_post = UPDATE sph_counter SET max_doc_id=(SELECT MAX(id) FROM sphinx_article) where counter_id=1 #sql_query_info_pre = SET NAMES utf8 #sql_query = SELECT * FROM article_info WHERE id=$id } # 主索引index定义 index article_main { source = article_main #对应的source名称 path = E:/PRO/2/sphinx/data/article_main mlock = 0 morphology = none min_word_len = 1 html_strip = 0 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定义 index article_delta:article_main { source = article_delta path = E:/PRO/2/sphinx/data/article_delta mlock = 0 morphology = none min_word_len = 1 html_strip = 0 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 } indexer { mem_limit = 128M } searchd { listen = 9312 listen = 9306:mysql41 log = E:/PRO/2/sphinx/log/searchd.log query_log = E:/PRO/2/sphinx/log/query.log read_timeout = 5 max_children = 30 pid_file = E:/PRO/2/sphinx/log/searchd.pid seamless_rotate = 1 preopen_indexes = 1 unlink_old = 1 workers = threads # for RT to work binlog_path = E:/PRO/2/sphinx/log }

然后建立数据主表,并插入一些数据作为搜索
CREATE TABLE sphinx_article (
id int(11) NOT NULL AUTO_INCREMENT,
title varchar(255) CHARACTER SET utf8 DEFAULT '',
cat_id tinyint(1) unsigned zerofill NOT NULL DEFAULT '0',
member_id int(11) unsigned NOT NULL,
content longtext CHARACTER SET utf8 NOT NULL,
created int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=139 DEFAULT CHARSET=latin1;
插入的数据如图: 主表数据如图
3.png

3.png

建立存储主表的最大id表,用于添加数据时sphinx的更新索引文件
CREATE TABLE sph_counter (
counter_id int(11) NOT NULL COMMENT '标识不同的数据表',
max_doc_id int(11) NOT NULL COMMENT '每个索引表的最大ID,会实时更新',
PRIMARY KEY (counter_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
接下来我们打开cmd窗口,进入目录E:\PRO\2\sphinx\bin 建立主索引,执行

E:\PRO\2\sphinx\bin\indexer.exe -c E:\PRO\2\sphinx\bin\sphinx.conf article_main
建立增量索引

E:\PRO\2\sphinx\bin\indexer.exe -c E:\PRO\2\sphinx\bin\sphinx.conf article_delta
如果运行上述命令行有错误,则根据错误提示去改动配置文件即可。

这时候你可以去看一下E:\PRO\2\sphinx\bin\data目录里面已经生成了索引文件(如下图所示,索引文件的名字对应你sphinx.conf中主索引index定义path的article_main)
索引文件生成
4.png

4.png

现在启动表示sphinx服务
E:/PRO/2/sphinx/bin/searchd.exe --config E:/PRO/2/sphinx/bin/sphinx.conf
启动成功如图所示(有错误就根据错误提示去更改配置文件): sphinx 启动成功如图
5.png
5.png

下面我们去完善搜索界面,前端代码

test.php

<?php header('Content-type:text/html;charset=utf-8'); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>sphinx test</title> </head> <body> <form name="form" method="get" action="index.php"> <label> <input style="width: 400px;" type="text" name="keyword"> </label> <label> <input type="submit" name="Submit" value="sphinx搜索"> </label> </form> </body> </html>

前端界面如下:
6.png

6.png

index.php文件

<?php /** * Created by ZhengNiu. * User: 77103 * Date: 2019/7/4 * Time: 16:32 */ header("Content-type:text/html;charset=utf-8;"); if (empty($_GET)) { header("Location:test.php"); } $keyword = $_GET['keyword']; if (trim($keyword) == '') { exit('请输入关键词'); } require_once './sphinx/api/sphinxapi.php'; $cl = new SphinxClient(); $cl->SetServer('localhost',9312); $res = $cl->Query($keyword, 'article_main'); $data = []; if (isset($res['matches']) && !empty($res['matches'])) { $ids = implode(',', array_keys($res['matches'])); $m = new Mysqli('localhost','root','123456','test'); if ($m->connect_errno) { exit($m->connect_error); } $dt = $m->query("SELECT id,title,cat_id,member_id,content,created FROM sphinx_article WHERE id IN" .'('. $ids .')'); while ($row = $dt->fetch_assoc()) { $data[] = $row; } } echo "<pre>"; print_r($data);

搜索结果:
7.png

7.png

还有一个问题未解决,如果我更新了或者添加了数据库记录,我每次都要运行一下重新生成索引文件???这样是不是太不灵活了。我们可以写一个sphinx.bat脚本,加入到windows 的计划任务中,这样就可以了。

添加数据库内容时更新索引文件原理:

1.新建一张表,记录一下上一次已经创建好索引的最后一条记录的ID
2.当索引时,然后从数据库中取出所有ID大于上面那个sphinx中的那个ID的数据, 这些就是新的数据,然后创建一个小的索引文件
3.把上边我们创建的增量索引文件合并到主索引文件上去
4.把最后一条记录的ID更新到第一步创建的表中
sphinx.bat 脚本内容

E:\PRO\2\sphinx\bin\indexer.exe -c E:\PRO\2\sphinx\bin\sphinx.conf article_main

E:\PRO\2\sphinx\bin\indexer.exe -c E:\PRO\2\sphinx\bin\sphinx.conf --merge article_main article_delta --rotate
加入到windows 任务计划启动即可(需要优化bat脚本隐藏执行)
加入计划任务的步骤:
计划任务
8.png

8.png

创建任务
9.png

9.png

为任务填写一个名称 任务名称

13.png

13.png

触发任务的条件

10.png

10.png

选择你要执行的bat脚本

16.png

16.png

完成查看列表
12.png

12.png

现在我们向数据库添加一些数据,再添加之前,我们先去看一下数据库的数据
sphinx_article 表 最大的id是138
sph_counter 表 记录的max_doc_id也是138
如图: sphinx_article
17.png

17.png

sph_counter表

18.png

18.png

下面我们运行插入一些数据

$m = new Mysqli('localhost','root','123456','test'); for ($i = 138; $i <= 140; $i++) { $add = [ 'id' => $i, 'title' => "我爱吃肉肉$i", 'cat_id' => rand(1, 99), 'member_id' => rand(1, 999), 'content' => uniqid(), 'created' => time() ]; $key = implode(",", array_keys($add)); $val = "'" . implode("','", array_values($add)) . "'"; $sql = "INSERT INTO `sphinx_article` ({$key}) VALUES ({$val})"; $m->query($sql); } $m->close();die;

这时候查看
sphinx_article 表 最大的id是140
sph_counter 表 记录的max_doc_id是138
我们的任务任务是每分钟一次。一分钟后我们去检索一下数据,看看可以查到我们新插入的两条数据不。

19.png

19.png

结果: 完成

21.png

21.png

到这里也就结束了。
源码地址: 链接:https://pan.baidu.com/s/1ai5Xlze98FX3RQefbcLspg 提取码:s6zy 复制这段内容后打开百度网盘手机App,操作更方便哦

Last modification:May 21, 2020
如果觉得我的文章对你有用,请随意赞赏