使用背景
在mysql中优化的时候,对varchar,char,text对这些数据进行查询时,如果我们使用like ‘%单词’,是无法使用到索引,如果网站的数据量比较大,会拖垮网站的速度。比如在根据电影的剧情来查找电影的名称,比如根据歌词查找歌名。
利用第三方搜索软件: Sphinx是一个独立的全文索引引擎,意图为其他应用提供高速、低空间占用、搜索结果高相关度的全文搜索功能。Sphinx可以非常容易的与SQL数据库和脚本语言集成。内置MySQL和PostgreSQL数据库数据源的支持。搜索API支持PHP、Python、Perl、Rudy和Java。
Coreseek介绍
Coreseek 是一款中文全文检索/搜索软件,基于Sphinx研发并独立发布,专攻中文搜索和信息处理领域,适用于行业/垂直搜索、论坛/站内搜索、数据库搜索、文档/文献检索、信息检索、数据挖掘等应用场景
Windows安装部署
1、下载解压,拷贝到我们指定一个目录下面
2、在etc目录下面,把mysql的模板配置文件拷贝到上级目录,并修改为sphinx.conf
3、配置数据源(对哪些数据进行建立索引)
建立索引源:在一个配置文件中,可以建立多个索引源的。语法:source 索引源的名称。
source 名称{
//具体的配置
}
#源定义source mysql
{
type = mysql
sql_host = localhost
sql_user = root
sql_pass =
sql_db = other
sql_port = 3306
sql_query_pre = SET NAMES utf8
sql_query = SELECT info_id as id, dev, goods_code, exclusive_price FROM import_fail
#sql_query第一列id需为整数
#title、content作为字符串/文本字段,被全文索引
#sql_attr_uint = group_id #从SQL读取到的值必须为整数
#sql_attr_timestamp = date_added #从SQL读取到的值必须为整数,作为时间属性
sql_query_info_pre = SET NAMES utf8 #命令行查询时,设置正确的字符集
sql_query_info = SELECT * FROM import_fail WHERE id=$id #命令行查询时,从数据库读取原始数据信息
#sql_query_post = update a set max_id = (select max(info_id) from import_fail) #把当前最大的id记录到表a
}
4、配置索引,一个数据源,要对应一个索引。语法:index 索引名
index a67{
//配置项
}
#index定义index mysql
{
source = mysql #对应的source名称
path = C:/wamp/bin/sphinx/var/data/fail #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...(此处fail为文件名不是目录)
docinfo = extern
mlock = 0
morphology = none
min_word_len = 1
html_strip = 0
#中文分词配置,详情请查看:http://www.coreseek.cn/products-install/coreseek_mmseg/
#charset_dictpath = /usr/local/mmseg3/etc/ #BSD、Linux环境下设置,/符号结尾
charset_dictpath = C:/wamp/bin/sphinx/etc/ #Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...
charset_type = zh_cn.utf-8
}
5、配置sphinx服务器
#searchd服务定义searchd
{
listen = 9312
read_timeout = 5
max_children = 30
max_matches = 1000
seamless_rotate = 1
preopen_indexes = 0
unlink_old = 1
pid_file = C:/wamp/bin/sphinx/var/log/fail.pid #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
log = C:/wamp/bin/sphinx/var/log/fail.log #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
query_log = C:/wamp/bin/sphinx/var/log/query.log #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
}
6、根据配置文件里面的配置,生成索引文件
要以管理员的方式进入到cmd,进入 到sphinx下面的bin目录
语法格式:执行sphinx下的一个程序indexer.exe –c配置文件 –all | 索引的名字
--all:为配置文件中所有的索引创建索引文件。也可以使用索引的名字只为某一个索引创建索引文件
生成的索引文件
7、要安装启动sphinx服务
语法:searchd.exe –c 配置文件 --install
该命令对应的参数:searchd开启服务端 searchd -c 配置文件 索引名称
服务器端默认监听 9312 端口。常用命令:
-c : 指定配置文件路径 --stop : 停止当前服务 --status : 查看当前状态 --install : 安装为 windows 服务
--delete: 删除windows服务 --port port: 监听的端口 --index indexName : 只查询某个索引,默认查询所有索引
LAMP安装部署
1.Lamp环境准备
2.下载支持中文的Sphinx ---> coreseek
3.安装环境
m4,gcc,gcc-c++,automake,libtool
4.安装中文分词组件mmseg
##安装mmseg
$ cd mmseg-3.2.14
$ ./bootstrap #输出的warning信息可以忽略,如果出现error则需要解决
$ ./configure --prefix=/usr/local/mmseg3
$ make && make install 5.安装coreseek前准备
依赖mysql及依赖库
mysql-server
mysql-devel 6.安装coreseek
$ cd csft-3.2.14 或者 cd csft-4.0.1 或者 cd csft-4.1
$ sh buildconf.sh #输出的warning信息可以忽略,如果出现error则需要解决
$ ./configure --prefix=/usr/local/coreseek --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg3/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg3/lib/ --with-mysql
$ make && make ins tall
配置
#
# Minimal Sphinx configuration sample (clean, simple, functional)
#source post
{
type = mysql
sql_host = localhost
sql_user = root
sql_pass =
sql_db = test
sql_port = 3306 # optional, default is 3306 #设置字符集
sql_query_pre = set names utf8
#设置数据来源
sql_query= select id,title,content from post #sql_attr_uint = group_id #从sql读取到的值必须为整数
#sql_attr_timestamp = date_added #从sql读取到的值必须为整数,作为时间属性 #提取具体数据
sql_query_info_pre = set names utf8 #命令查询时设置正确的字符集
sql_query_info = SELECT * FROM post WHERE id=$id #命令查询时从数据库读取原始数据信息
} #配置索引
index ind_post
{
source = post #必须和源名称一致
path = /usr/local/coreseek/var/data/post #配置生成的索引文件的存储路径
docinfo = extern
#去除html标签
html_strip = 1
#完整的去除指定标签
html_remove_elements = style,script
#去除标签的时候,留下点东西
html_index_attrs = img=title,alt; a=title,alt
#设置索引字符集
charset_type = zh_cn.utf-8
#设置词典
charset_dictpath = /usr/local/mmseg3/etc/
} indexer
{
mem_limit = 32M
} searchd
{
port = 9312
log = /usr/local/coreseek/var/log/searchd.log
query_log = /usr/local/coreseek/var/log/query.log
read_timeout = 5
max_children = 30
pid_file = /usr/local/coreseek/var/log/searchd.pid
max_matches = 1000
seamless_rotate = 1
preopen_indexes = 0
unlink_old = 1
}
使用
1.基本搜索
开启服务接口
/usr/local/coreseek/bin/searchd -c /usr/local/coreseek/etc/csft.conf
2.处理高亮 $opts = array(
"before_match" => "<span style="color:red">",
"after_match" => "</span>"
); foreach($list as $key=>$val){
$list[$key] = $sp->buildExcerpts($val,"ind_post",$keyword,$opts);
} 注意:处理后会变为索引数组
3.设置匹配模式
$sp->setMatchMode(SPH_MATCH_ANY); (1)SPH_MATCH_ALL 完全匹配所有的词
如“冬天 的 雪”,并不会匹配 “我爱冬天”,但可以匹配 “我的朋友,爱冬天,和雪”。因为“冬天的雪” 被分成 “冬天”,“的”,“雪”三个词,匹配条件是同时包含这三个词,“我爱冬天”里只包含一个“冬天”
(2)SPH_MATCH_ANY 匹配任意一个词
如“冬天 的 雪”,并会匹配 “我爱冬天”。"冬天的雪“ -》 ”冬天“ ”的“ ”雪“,因为“我爱冬天”里有一个“冬天”相匹配
(3)SPH_MATCH_PHRASE 必须匹配整个短语
如“冬天的雪”,不会匹配 “我的朋友,爱冬天,和雪”,虽然都包含同样的需要严格匹配不再健忘,只匹配“冬天的雪”
(4)SPH_MATCH_BOOLEAN 与,或,非,分组 &,or,!,()
如:hello | world,查询“手机”,或“冬天”,:
<?php
$sc = new SphinxClient();
$res = $sc->query("手机|冬天");
(5)SPH_MATCH_EXTENDED 支持一些扩展的语法
支持 @字段 查询,如查询title包含 abc , content 包含 bcd的:'@title abc @content bcd'
4.设置排序模式
1.按照默认权重排序
$sp->setSortMode(SPH_SORT_EXTENDED,"@weight desc"); 2.人工干预排序
1.配置文件设置属性字段
sql_attr_uint = weight
2.重建索引
3.排序
$sp->setSortMode(SPH_SORT_EXTENDED,"weight desc @weight desc");====================================
#开启去除标签
html_strip = 1#去除标签的时候留下的信息
html_index_attrs = img=alt,title; a=title;#完整去除的标签
html_remove_elements = style, script====================================
增量索引
1.给数据库添加一张表,记录完整索引位置
create table a(max_id int);
2.修改配置文件中的主索引配置项,目的建完索引后,把最大的id存储到该表中
3.添加增量数据源
4.主索引不变,添加增量索引
5.重新建立主索引,要把最大的id值保存的a表里面
6.把增量索引合并到主索引上面
7.可以结合操作系统的计划任务做定时脚本
每天晚上4:30做主索引,每5分钟做增量索引
30 4 * * * /usr/local/coreseek/bin/indexer ind_post --rotate
*/5 * * * * /usr/local/coreseek/bin/indexer ind_postnew --rotate
====================================
更新词典词条
1.编辑/usr/local/mmseg3/etc/unigram.txt 词典模板文件
2. ../bin/mmseg -u unigram.txt 重新得到词典
3.替换词典 mv unigram.txt.uni uni.lib
4.重新创建索引
具体代码
<?php header("content-type:text/html;charset=utf-8"); //包含类文件 require "C:/wamp/bin/sphinx/api/sphinxapi.php"; //ini_set("display_errors", "Off"); //error_reporting(E_ALL^E_NOTICE^E_WARNING);
//接收关键字
$keyword = $_GET["keyword"];
//实例化sphinx对象
$sp = new SphinxClient();
//连接服务器
$sp->setServer("localhost",9312);
//设置匹配模式
$sp->setMatchMode(SPH_MATCH_ANY);
//设置返回结果集偏移量和数目
$sp->setLimits(0,1000);
//执行搜索
$result = $sp->query($keyword,"mysql");
//var_dump($result);exit;
if($result["total"] == 0) exit("查无数据");
//整理所有id
$ids = join(",",array_keys($result["matches"]));
//var_dump($ids);exit;
//连接数据库查数据
$conn = mysql_connect("localhost",'root','') or die("error connecting");
mysql_query("set names utf8");
mysql_select_db('other',$conn);
$sql = "select info_id , dev, goods_code, exclusive_price from import_fail where info_id in ({$ids})";
$res = mysql_query($sql,$conn);
$data = array();
while($row = mysql_fetch_assoc($res)){
$data[] = $row;
}
//var_dump($data);exit;
$opts = array(
"before_match" => "<span style='color:red'>",
"after_match"=> "</span>"
);
//处理结果
foreach($data as $key=>$val){
$val = $sp->buildExcerpts($val,"mysql",$keyword,$opts);
echo $val[1]."<br/>".$val[2]."<hr/>";
}
?>