[置顶] 【中文分词-全文搜索】Ubuntu 16.04 Mysql和PHP 配置 Sphinx-for-chinese 及Sphinx的排序筛选分页基本操作

时间:2021-08-05 08:19:58

记录在此,作为分享,也作为自己的存档。


不要用原生Sphinx,因为中文支持不好。要用sphinx-for-chinese,数据库编码要用utf-8,既能很好的受sphinx支持,又符合php规范。

git clone https://github.com/eric1688/sphinx


cd sphinx

./configure --prefix=/usr/local/sphinx --with-mysql

make & make install

从xdict_1.1.txt生成xdict文件,xdict_1.1.txt文件可以根据需要进行修改

/usr/local/sphinx/bin/mkdict xdict_1.1.txt xdict

xdict生成完成显示:

Preparing...
Making Chinese dictionary: 100% |******************************|
Total words: 284757
File size: 2854912 bytes
Compression ratio: 100 %
Chinese dictionary was successfully created!

将xdict放入sphinx目录:

cp xdict /usr/local/sphinx/etc/

修改sphinx.conf索引配置文件:

cd /usr/local/sphinx/etc/

cp sphinx.conf.dist sphinx.conf

vim sphinx.conf


配置文件参考网上一个人写的吧,搬来:

# sphinx基本配置 
# 索引源
source goods_src
{
# 数据库类型
type = mysql
# MySQL主机IP
sql_host = localhost
# MySQL用户名
sql_user = sphinxuser
# MySQL密码
sql_pass = sphinxpass
# MySQL数据库
sql_db = sphinx
# MySQL端口(如果防火墙有限制,请开启)
sql_port= 3306
# MySQL sock文件设置(默认为/tmp/mysql.sock,如果不一样,请指定)
sql_sock = /tmp/mysql.sock
# MySQL检索编码(数据库非utf8的很可能检索不到)
sql_query_pre = SET NAMES UTF8
# 获取数据的SQL语句
sql_query = SELECT goods_id,goods_id AS goods_id_new,goods_name,goods_color,goods_name AS goods_name_search,goods_color AS goods_color_search From goods_test
# 以下是用来过滤或条件查询的属性(以下字段显示在查询结果中,不在下面的字段就是搜索时要搜索的字段,如SQL语句中的goods_color_search,goods_name_search)
# 无符号整型
#goods_id为主键,如果加在这里在生成索引的时候会报attribute 'goods_id' not found,这里用goods_id_new来变通
sql_attr_uint = goods_id_new
# 字符串类型
sql_attr_string = goods_name
sql_attr_string = goods_color
# 用于命令界面端(CLI)调用的测试(一般来说不需要)
#sql_query_info = SELECT * FROM goods_test Where goods_id = $goods_id;
}
# 索引
index goods
{
# 索引源声明
source = goods_src
# 索引文件的存放位置
path = /usr/local/sphinx/var/data/goods
# 文件存储模式(默认为extern)
docinfo = extern
# 缓存数据内存锁定
mlock = 0
# 马氏形态学(对中文无效)
morphology = none
# 索引词最小长度
min_word_len = 1
# 数据编码(设置成utf8才能索引中文)
charset_type = utf-8
# 中文分词词典
chinese_dictionary = /usr/local/sphinx/etc/xdict
# 最小索引前缀长度
min_prefix_len = 0
# 最小索引中缀长度
min_infix_len = 1
# 对于非字母型数据的长度切割(for CJK indexing)
ngram_len = 1
# 对否对去除用户输入查询内容的html标签
html_strip = 0
}
# 索引器设置
indexer
{
# 内存大小限制 默认是 32M, 最大 2047M, 推荐为 256M 到 1024M之间
mem_limit = 256M
}
# sphinx服务进程search的相关配置
searchd
{
# 监测端口及形式,一下几种均可,默认为本机9312端口
# listen = 127.0.0.1
# listen = 192.168.0.1:9312
# listen = 9312
# listen = /var/run/searchd.sock
# search进程的日志路径
log = /usr/local/sphinx/var/log/searchd.log
# 查询日志地址
query_log = /usr/local/sphinx/var/log/query.log
# 读取超时时间
read_timeout = 5
# 请求超时市时间
client_timeout = 300
# searche进程的最大运行数
max_children = 30
# 进程ID文件
pid_file = /usr/local/sphinx/var/log/searchd.pid
# 最大的查询结果返回数
max_matches = 1000
# 是否支持无缝切换(做增量索引时需要)
seamless_rotate = 1
# 在启动运行时是否提前加载所有索引文件
preopen_indexes = 0
# 是否释放旧的索引文件
unlink_old = 1
# MVA跟新池大小(默认为1M)
mva_updates_pool = 1M
# 最大允许的网络包大小(默认8M)
max_packet_size = 8M
# 每个查询最大允许的过滤器数量(默认256)
max_filters = 256
#每个过滤器最大允许的值的个数(默认4096)
max_filter_values = 4096
# 每个组的最大查询数(默认为32)
max_batch_queries = 32
}
# Sphinx配置文件结束

配置好了,增加索引:

/usr/local/sphinx/bin/indexer  -c /usr/local/sphinx/etc/sphinx.conf goods

如果配置文件里有多个索引,需要一次生成使用--all参数
/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf --all

开启守护进程

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

如果重建索引时守护进程正在运行,需要运行下面的指令,会重建索引并且重开守护进程

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

ubuntu 关闭 iptables
ufw disable 


把 git目录下sphinx/api/sphinxapi.php copy 出来,然后做一个php类,位于 /project/model/sphinxclient.php:(项目结构请见 一个简单的php mvc框架 )

<?php
include_once(LIBRARY_PATH ."/sphinxapi.php");
class Model_SphinxClient extends SphinxClient {

protected static $_instance = null;

public static function instance(){
if(self::$_instance == null){
self::$_instance = new self();

self::$_instance->SetServer('127.0.0.1',9312);

self::$_instance->SetConnectTimeout(3);

self::$_instance->SetMaxQueryTime(2000);

}
return self::$_instance;
}

}

调用sphinx时,就这样:


$sphinx = Model_SphinxClient::instance();
//...//排序
//...//分页
//...//筛选等
$data = $sphinx->Query($keywords,$indexName);
//拿到$data里的id后,再到数据库查数据


其余sphinx具体操作(最基本的排序、筛选、分页): 详细的见官方文档:http://sphinxsearch.com/docs/current.html 


按价格排序:(其余依此类推) 排序

配置文件里面设置
sql_attr_float = price
然后php:

$sphinx->SetSortMode (SPH_SORT_ATTR_DESC,price);//相当于sql 的 order by price desc
$sphinx->SetSortMode (SPH_SORT_ATTR_ASC,price);//相当于sql 的 order by price asc

按体重筛选筛选1
配置文件里面设置
sql_attr_uint = weight

然后php:

$sphinx->SetFilterRange("weight",42,50);//筛选42kg到50kg之间的姑娘

按罩杯筛选姑娘:筛选2

配置文件sql_query 的 select里面 记得 CRC32(cup) as cup
sql_attr_uint = cup

然后php:

$sphinx->SetFilter("cup",array(crc32('B'),crc32('C')));//筛选出罩杯B或者C的
$sphinx->SetFilter("cup",array(crc32('C')));//只要C罩杯的

分页:分页

$sphinx->SetLimits($offset,$limit);//总数见查询结果total_found


容易犯的错误记录:

排序:官方文档说了“不要将匹配模式常量放到引号里面”,那样会导致排序失效!

WARNING: (PHP specific) you must not take the matching mode constant name in quotes, that syntax specifies a string and is incorrect:

$cl->SetSortMode ( "SPH_SORT_ATTR_DESC" ); // INCORRECT! will not work as expected
$cl->SetSortMode ( SPH_SORT_ATTR_ASC ); // correct, works OK