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

何甫
2023-12-01

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


不要用原生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




 类似资料: