转自 http://blog.csdn.net/qq157962718/article/details/50985562 做了部分修改
架构使用图例
优势
- 数据库搜索,如果搜索范围包括全部正文数据,往往性能很低,用户响应时间长(分钟级,经常超时);而全文检索可以在0.X秒(毫秒级)的时间内将结果反馈给用户。
- 数据库搜索,一个用户在搜索,往往会影响其他用户对应用系统进行操作;全文检索可以同时支持多个用户并发搜索,不影响其他用户对应用系统的操作。
- 支持不同的搜索模式(“完全匹配”,“短语匹配”,“任意匹配”)。
- 数据库搜索很难实现多个关键字的复合搜索;而全文检索可以实现,包括“和(AND)”、“或(OR)”、“否(NOT)”等。
- 数据库搜索难于对结果进行相关度排序,当检索结果多时;用户往往难于找到最恰当的文档;而全文检索通过统计的研究成果,可以将文档进行相关度排序后,再返回给用户,提高用户的效率。
- 全文检索还可以对检索结果的数据进行聚类分析(Group,这里的聚类和NLP里面的聚类算法不同),增进用户对数据分布情况的了解。
- 优秀的全文检索系统支持按照文档的不同字段分配不同的检索权重,根据应用的不同,动态的改变结果的排序。
- 对于中文、日文和韩文而言,全文检索支持分词,进一步缩小了结果集的范围;而数据库检索往往不支持,往往一些与搜索词毫不相干的内容也会混进结果集。
- 在单一CPU上,最高可对100GB的文件建立索引,单一索引可包括100MB文件。
- 支持主从式的分布式搜索,单一节点失效不影响整个搜索系统。
劣势
- 全文检索需要用户定时执行建立索引的动作,比直接使用数据库搜索增加了维护的工作。
- 对于全英文数据建立索引的速度可达10MB/秒,在启用中文分词后,建立索引的速度只有300KB/秒。
- 实现的不完善的全文检索系统容易造成索引与数据库的不一致,反而可能会降低用户的使用体验。
安装环境
- CentOS7.3.1
- LNMP
- PHP5.6.22
- nginx
- MySQL5.6.29
- coreseek3.2.14稳定版
- 需要预装软件:gcc、g++、gcc-c++、libtool、autoconf、automake、imake、mysql-devel、libxml2-devel、expat-devel
安装流程
下载coreseek3.2.14稳定版(此链接无法下载,自行在csdn其他地址下载)
- 1
- 2
- 3
需要先安装mmseg中文分词!!
- 1
- 2
- 3
报错!
解决方法:
第一种:
- 1
- 2
第二种:依次执行
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
安装csft
- 1
- 2
- 3
- 4
- 5
csft报错:
make[2]: *** [tokenizer_zhcn.o] Error 1
make[2]: Leaving directory `/home/zyf/zyfwork/csft3.1b3/src’
make[1]: *** [all] Error 2
make[1]: Leaving directory `/home/zyf/zyfwork/csft3.1b3/src’
make: *** [all-recursive] Error 1
/usr/local/sphinx/src/sphinx.cpp:15557: undefined reference to `libiconv_open’
libsphinx.a(sphinx.o)(.text+0x53a01):/usr/local/sphinx/src/sphinx.cpp:15575: undefined
reference to `libiconv’
libsphinx.a(sphinx.o)(.text+0x53a28):/usr/local/sphinx/src/sphinx.cpp:15581: undefined
reference to `libiconv_close’
collect2: ld returned 1 exit status
make[2]: * [indexer] Error 1
make[2]: Leaving directory `/usr/local/sphinx/src’
make[1]: * [all] Error 2
make[1]: Leaving directory `/usr/local/sphinx/src’
make: * [all-recursive] Error 1
g++ -DHAVE_CONFIG_H -I. -I../config -DSYSCONFDIR="\"/opt/coreseek-3.2.14/etc\"" -DDATADIR="\"/opt/coreseek-3.2.14/var/data\"" -I/usr/local/include -pthread -I/usr/include/mysql -fPIC -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -DBIG_JOINS=1 -fomit-frame-pointer -g -I/opt/mmseg-3.2.14/include/mmseg/ -Wall -g -D_FILE_OFFSET_BITS=64 -O3 -DNDEBUG -MT sphinxexpr.o -MD -MP -MF .deps/sphinxexpr.Tpo -c -o sphinxexpr.o sphinxexpr.cpp
sphinxexpr.cpp: In constructor ‘ExprParser_t::ExprParser_t(CSphSchema*, ISphExprHook*)’:
sphinxexpr.cpp:742:17: warning: ‘ExprParser_t::m_pExtra’ will be initialized after [-Wreorder]
sphinxexpr.cpp:711:19: warning: ‘ISphExprHook* ExprParser_t::m_pHook’ [-Wreorder]
sphinxexpr.cpp:698:2: warning: when initialized here [-Wreorder]
..........................................................
sphinxexpr.cpp:1746:43: error: ‘ExprEval’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
sphinxexpr.cpp:1746:43: note: declarations in dependent base ‘Expr_ArgVsSet_c<int>’ are not found by unqualified lookup
sphinxexpr.cpp:1746:43: note: use ‘this->ExprEval’ instead
make[2]: *** [sphinxexpr.o] Error 1
make[2]: Leaving directory `/home/mac/Downloads/coreseek-4.1-beta/csft-4.1/src'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/home/mac/Downloads/coreseek-4.1-beta/csft-4.1/src'
make: *** [all-recursive] Error 1
将所有的:
T val = ExprEval ( this-m_pArg, tMatch );
交换成
T val = this-ExprEval ( this-m_pArg, tMatch );
# make
配置简单说明
- 1
- 1
新建索引增量表
CREATE TABLE `m_sph_counter` (
`counter_id` int(11) NOT NULL AUTO_INCREMENT,
`max_doc_id` int(11) DEFAULT NULL,
PRIMARY KEY (`counter_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
coreseek配置文件
配置文件路径 /usr/local/coreseek/etc/sphinx.conf.dist
复制一份改名为csft.conf
默认配置文件名:csft.conf
一般情况下,sql_query给出读取数据的SQL语句,第一列为自增ID字段,然后可以包括字符串字段,整数数值字段,整数数值字段需要在后面使用sql_attr_uint明确标注,有多个则分别标注即可。
贴上我配置后的信息
csft.conf
#源定义
source mysql
{
type = mysql
sql_host = #数据库ip地址
sql_user = root
sql_pass = #数据库密码
sql_db = test #数据库名
sql_sock = /tmp/mysql.sock #使用xshell找到你的mysql.sock地址路径
sql_port = 3306
sql_query_pre = SET NAMES utf8
sql_query_pre = replace into m_sph_counter select 1,max(id) from m_documents
sql_query = SELECT id,group_id,UNIX_TIMESTAMP(date_added) AS date_added,title,content FROM m_documents where id<=(SELECT max_doc_id FROM m_sph_counter WHERE counter_id = 1)
#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 m_documents WHERE id=$id #命令行查询时,从数据库读取原始数据信息
}
#增量源定义
source delta :mysql
{
sql_query_pre = SET NAMES utf8
sql_query = SELECT id,group_id,UNIX_TIMESTAMP(date_added) AS date_added,title,content FROM m_documents where id<=(SELECT max_doc_id FROM m_sph_counter WHERE counter_id = 1)
}
#index定义
index mysql
{
source = mysql #对应的source名称
path = /usr/local/coreseek/var/data/
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/mmseg/etc/ #BSD、Linux环境下设置,/符号结尾
#charset_dictpath = etc/ #Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...
charset_type = zh_cn.utf-8
}
#增量index定义
index delta : mysql
{
source = delta
path = /usr/local/coreseek/var/data/delta
}
#全局index定义
indexer
{
mem_limit = 128M
}
#searchd服务定义
searchd
{
listen = 9312
read_timeout = 5
max_children = 30
max_matches = 1000
seamless_rotate = 0
preopen_indexes = 0
unlink_old = 1
pid_file = /usr/local/coreseek/var/log/searchd_mysql.pid
log = /usr/local/coreseek/var/log/searchd_mysql.log
query_log = /usr/local/coreseek/var/log/query_mysql.log
}
mmseg配置文件
配置文件路径:/usr/local/mmseg/etc/
测试中文分词:
- 1
结果:
常用使用方法和操作说明
搜索服务
(必须最先开启,否则后续操作会缺少必要的参数文件)
- 1
- 2
启动服务会有一些报错,没有error错误暂时跳过
- 1
- 2
生成索引
- 1
- 2
生成索引根据error报错信息一个个调错
报错1:
解决1:
报错2:MySQL需要sock文件
解决2:修改coreseek配置文件
报错3:词库路径错误
解决3:修改coreseek配置文件
成功:
更新索引
- 1
搜索检测
- 1
增量索引
利用crontab定时任务,3.2.14唯一的增量索引方法;
WINDOWS本地连接LINUX数据库会出现权限问题
- 1
自动脚本
all.sh(重建全部索引)
- 1
- 2
- 3
delta.sh(生成增量索引)
- 1
- 2
- 3
- 1
- 1
- 2
PHP操作coreseek
coreseek安装包里有接口文件:/testpack/api/sphinxapi.php
;
也可以使用sphinx扩展(推荐)。
安装sphinx扩展
- 1
- 2
- 3
error: Cannot find libsphinxclient headers
# cd /usr/local/src/coreseek-3.2.14/csft-3.2.14/api/libsphinxclient
# ./configure
# make && make install
安装完libsphinxclient,继续安装sphinx扩展
# cd /usr/local/src/sphinx-1.1.0
# /usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config
# make && make install
这里有个报错
修改 sphinx.c 第105行为:
root@iZ282i5hw2tZ:~/sphinx-1.1.0# make
/bin/bash /root/sphinx-1.1.0/libtool --mode=compile cc -I. -I/root/sphinx-1.1.0 -DPHP_ATOM_INC -I/root/sphinx-1.1.0/include -I/root/sphinx-1.1.0/main -I/root/sphinx-1.1.0 -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/TSRM -I/usr/include/php5/Zend -I/usr/include/php5/ext -I/usr/include/php5/ext/date/lib -I/usr/local/include -DHAVE_CONFIG_H -g -O2 -c /root/sphinx-1.1.0/sphinx.c -o sphinx.lo
libtool: compile: cc -I. -I/root/sphinx-1.1.0 -DPHP_ATOM_INC -I/root/sphinx-1.1.0/include -I/root/sphinx-1.1.0/main -I/root/sphinx-1.1.0 -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/TSRM -I/usr/include/php5/Zend -I/usr/include/php5/ext -I/usr/include/php5/ext/date/lib -I/usr/local/include -DHAVE_CONFIG_H -g -O2 -c /root/sphinx-1.1.0/sphinx.c -fPIC -DPIC -o .libs/sphinx.o
/root/sphinx-1.1.0/sphinx.c: In function 'php_sphinx_client_read_property':
/root/sphinx-1.1.0/sphinx.c:105:2: error: too few arguments to function 'std_hnd->read_property'
retval = std_hnd->read_property(object, member, type TSRMLS_CC);
^
/root/sphinx-1.1.0/sphinx.c: In function 'zim_SphinxClient_updateAttributes':
/root/sphinx-1.1.0/sphinx.c:1040:6: warning: passing argument 2 of 'memset' makes integer from pointer without a cast [enabled by default]
memset(vals_mva, NULL, values_mva_size);
^
In file included from /usr/include/features.h:374:0,
from /usr/include/stdlib.h:24,
from /usr/include/php5/main/php_config.h:2418,
from /usr/include/php5/main/php.h:33,
from /root/sphinx-1.1.0/sphinx.c:26:
/usr/include/x86_64-linux-gnu/bits/string3.h:76:1: note: expected 'int' but argument is of type 'void *'
__NTH (memset (void *__dest, int __ch, size_t __len))
^
/root/sphinx-1.1.0/sphinx.c: In function 'zm_startup_sphinx':
/root/sphinx-1.1.0/sphinx.c:1888:43: warning: assignment from incompatible pointer type [enabled by default]
php_sphinx_client_handlers.read_property = php_sphinx_client_read_property;
^
make: *** [sphinx.lo] Error 1
修改 sphinx.c
retval = std_hnd->read_property(object, member, type TSRMLS_CC, NULL);
然后编译即可通过
在查看目录
# cd /usr/php/lib/php/extensions/no-debug-non-zts-20131226/
# ls
发现sphinx.so已经存在
修改php.ini
# cd /usr/local/php/etc/重启服务器,查看phpinfo
# lnmp restart
PHP测试:
public function ceshisphinx()
{
$sphinx = new \SphinxClient(); //实例化sphinx类
//sphinx的主机名和端口
$sphinx->SetServer('127.0.0.1',9312);
$key_word = 'Opera';
//设置返回结果集为php数组格式
$sphinx->SetArrayResult ( true );
//匹配结果的偏移量,参数的意义依次为:起始位置,返回结果条数,最大匹配条数
$sphinx->SetLimits(0, 100, 1000); //100表示传递的获取条数
//最大搜索时间
$sphinx->SetMaxQueryTime(10);
//执行简单的搜索,这个搜索将会查询所有字段的信息,要查询指定的字段请继续看下文
$index = '*' ;//索引源是配置文件中的 index 类,如果有多个索引源可使用,号隔开:'email,diary' 或者使用'*'号代表全部索引源
$result = $sphinx->query($key_word,$index);
$ids=array_keys($result['matches']);
$database_name = 'test'; //读取数据库对应资源
$data_str = "mysql://root:".C('DB_PWD')."@localhost:3306/$database_name";
$new_dao = M()->db(1,$data_str);
$where['id'] = array('in',$ids);
$res = $new_dao->table('m_documents')->field('id,title,content')->where($where)->select();
echo '查找的关键字--------------------'.$key_word.'<br>';
dump($res); //打印数据
//释放资源
$sphinx=null;
}
打印的数据:
查找的关键字--------------------Opera
array(100) {
[0] => array(3) {
["id"] => string(1) "3"
["title"] => string(47) "死都要上!Opera Mini 体验版抢先试用"
["content"] => string(2255) "Opera一直都被认为是浏览"
}
[1] => array(3) {
["id"] => string(1) "6"
["title"] => string(47) "死都要上!Opera Mini 体验版抢先试用"
["content"] => string(2255) "Opera一直都被认为是浏览"
}
[2] => array(3) {
["id"] => string(1) "9"
["title"] => string(47) "死都要上!Opera Mini 体验版抢先试用"
["content"] => string(2255) "Opera一直都被认为是浏览"
}
[3] => array(3) {
["id"] => string(2) "12"
["title"] => string(47) "死都要上!Opera Mini 体验版抢先试用"
["content"] => string(2255) "Opera一直都被认为是浏览"
}
[4] => array(3) {