搭建Sphinx全文搜索引擎

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/okiwilldoit/article/details/78872290

目前,全文搜索引擎主要有三种:
Lucene系, 包含solr 和 elasticsearch,Java支持的很好;
sphinx,c++开发, 简单高性能,
Xapian,c++开发, 国内的 xunsearch 基于Xapian

Sphinx(斯芬克司)是一个基于SQL的全文检索引擎,可以结合MySQL,PostgreSQL做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。Sphinx特别为一些脚本语言设计搜索API接口,如PHP,Python,Perl,Ruby等,同时为MySQL也设计了一个存储引擎插件。

Sphinx 单一索引最大可包含1亿条记录,在1千万条记录情况下的查询速度为0.x秒(毫秒级)。Sphinx创建索引的速度为:创建100万条记录的索引只需 3~4分钟,创建1000万条记录的索引可以在50分钟内完成,而只包含最新10万条记录的增量索引,重建一次只需几十秒。

Sphinx的主要特性包括:
高速索引 (在新款CPU上,近10 MB/秒); 高速搜索 (2-4G的文本量中平均查询速度不到0.1秒); 高可用性 (单CPU上最大可支持100 GB的文本,100M文档); 提供良好的相关性排名 支持分布式搜索; 提供文档摘要生成; 提供从MySQL内部的插件式存储引擎上搜索 支持布尔,短语, 和近义词查询; 支持每个文档多个全文检索域(默认最大32个); 支持每个文档多属性; 支持断词; 支持单字节编码与UTF-8编码;

Sphinx是开源的搜索引擎,它支持英文的全文检索。所以如果单独搭建Sphinx,你就已经可以使用全文索引了。但是往往我们要求的是中文索引,怎么做呢?国人提供了一个可供企业使用的,基于Sphinx的中文全文检索引擎。也就是说Coreseek实际上的内核还是Sphinx。

Coreseek发布了3.2.14版本和4.1版本,其中的3.2.14版本是2010年发布的,它是基于Sphinx0.9.9搜索引擎的。而4.1版本是2011年发布的,它是基于Sphinx2.0.2的。Sphinx从0.9.9到2.0.2还是有改变了很多的,有很多功能,比如sql_attr_string等是在0.9.9上面不能使用的。所以在安装之前请判断清楚你需要安装的是哪个版本,在google问题的时候也要弄清楚这个问题的问题和答案是针对哪个版本的。这里建议使用4.1版本。

1. 软件安装

常见版本:4.1,3.2.14 (建议4.1)
下载软件包 coreseek-4.1-beta.tar.gz
解压:tar -zxvf coreseek-4.1-beta.tar.gz

官网已不再维护,只能从别的地方去下载。

2. 安装mmseg分词软件

cd mmseg-3.2.14
./ bootstrap
./configure --prefix=/usr/local/mmseg3
make && make install

建立mmseg软链接:

ln -s /usr/local/mmseg3/bin/mmseg /usr/local/bin/

3. 测试分词效果

vim abc
输入:我们来到了天安门广场

mmseg  -d  /usr/local/mmseg3/etc  abc

需要在-d后加上unigram.txt文件的路径,即/usr/local/mmseg3/etc

unigram.txt是字典文本,可以在里面添加你自己的关键字。
然后使用:mmseg -u unigram.txt 生成字典文件:unigram.txt.uni 然后重命名一下 uni.lib
这个就是sphinx 认识的字典了。

4. 安装 Coreseek搜索引擎

cd csft-4.1
sh buildconf.sh
./configure --prefix=/usr/local/coreseek  --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg3/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg3/lib
make && make install

5. 创建索引配置文件:

(1)单库单表
在/usr/local/coreseek/etc下创建一个配置文件sphinx.conf
输入以下配置:

source product_name
{
    type = mysql
    sql_host = 192.168.120.146
    sql_user = root
    sql_pass = root
    sql_db = db_name
    sql_port = 3306
    sql_query_pre = SET NAMES utf8
    sql_query_range = SELECT MIN(Fid), MAX(Fid) FROM t_product_base
    sql_range_step = 500
    ## SELECT的第一个字段是非负整数并且值都不相同的,搜索结果返回的document ID就是这个,建议使用数据表的主键,这里是Fid
    ## 其它字段是用来设置搜索条件和希望被搜索的字段,如果那个字段你认为对搜索没有作用,那就不要选择
    ## 搜索引擎会为字符串类型的字段建立索引
    sql_query = SELECT Fid, Fproduct_spu_id, Fproduct_name, Frow_modify_time \
        FROM t_product_base WHERE Fid>$start  and  Fid<$end \
        ORDER BY Frow_modify_time DESC
    ## sql_attr_是索引属性,主要被用来设置搜索条件,并且搜索结果返回的信息也包含这些属性的值,设置某个属性的前提是在sql_query中有返回这个字段的数据

    ## 类型有sql_attr_uint,sql_attr_bigint,sql_attr_bool,sql_attr_float,sql_field_string,sql_attr_timestamp等

    sql_attr_uint = Fid
    sql_attr_uint = Fproduct_spu_id
    sql_field_string = Fproduct_name
    sql_attr_timestamp = Frow_modify_time

    sql_query_info_pre  = SET NAMES utf8
    #调试用,只支持命令行,api不支持,多库查询会有问题,只会查询第一张表
    sql_query_info  = SELECT * FROM t_product_base WHERE Fid=$id
}

#索引名
index product_name_idx
{
    source = product_name
    ##存放位置
    path = /usr/local/coreseek/var/data/product_name
    docinfo = extern
    charset_type = zh_cn.utf-8
    #Unigram dictionary路径,必须要有
    charset_dictpath = /usr/local/mmseg3/etc
    html_strip = 0
    #停止词
    stopwords = /usr/local/coreseek/dict/stopwords/stopwords.txt
}

indexer
{
    mem_limit = 128M
}

searchd
{
    port = 9351
    log = /usr/local/coreseek/var/log/search_product_name.log
    query_log = /usr/local/coreseek/var/query_product_name.log
    read_timeout = 5
    max_children = 30
    pid_file = /usr/local/coreseek/var/searchd_product_name.pid
    max_matches = 10000
    seamless_rotate = 1
    preopen_indexes = 0
    unlink_old = 1
}

停用词txt格式:

',','。',' ','请','是','但','从','到','和','或','在','有','又','了','将','什么','么','虽','吗','嘛','啊','呢','哈','呵','噢','哦','嗯','吧','哎','哟','呀','唉','啦','呗','嗬','兮','乎','矣','哉','就','这','那','他','她','它','们','你','您','的','得','很','的','岛国','!','?',':','、',';','…','(',')','/','-','_','=','《','》','+','|','*','&','%','$','#','@','`','~','<','>','[',']','{','}'

(2)多服务器 多库 多表

## sphinx 多服务器 多库 多表 取源数据
source product_name
{
    type = mysql
    sql_query_pre = SET NAMES utf8
    sql_query_info_pre = SET NAMES utf8
    mysql_connect_flags  = 32
}

## N台服务器 N个库 N个表
## 第一台服务器参数
source host0:product_name
{
    sql_host = 192.168.120.146
    sql_user = root
    sql_pass = root
    sql_port = 3306
}

## 第二台服务器参数
source host1:product_name
{
    sql_host = 192.168.120.146
    sql_user = root
    sql_pass = root
    sql_port = 3306
}

## 从第一台服务器中取源
source host0_source:host0
{
    ## 表结构 有3个整型字段 用户id,Fseller_id,Fid。 共N个库 每个库N张表(此处用一张表,多张表用UNION)
    ## id为索引document默认id, 必须是整数, 本身不支持自增, 需自行拼写,此处用Fseller_id作为前缀
    sql_query = SELECT CONCAT(Fseller_id, Fid) AS id, Fseller_id, Fid, Fproduct_name FROM t_product_base

    sql_attr_uint = Fseller_id
    sql_attr_uint = Fid

    sql_field_string = Fproduct_name
}

## 取每个库数据源
source host0_db0_source:host0_source
{
    sql_db = db_0
    #调试用,只支持命令行,api不支持,多库查询会有问题,只会查询第一张表
    sql_query_info  = SELECT * FROM t_product_base as t WHERE Fid=substr($id, 2) and Fseller_id=substr($id,1,1)

}

source host0_db1_source:host0_source
{
    sql_db = db_1
}

## 从第二台服务器中取源
source host1_source:host1
{
    sql_query = SELECT CONCAT(Fseller_id, Fid) AS id, Fseller_id, Fid, Fproduct_name FROM t_product_base

    sql_attr_uint = Fseller_id
    sql_attr_uint = Fid

    sql_field_string = Fproduct_name
}

source host1_db0_source:host1_source
{
    sql_db = db_3
}

source host1_db1_source:host1_source
{
    sql_db = db_4
}

#索引名
index product_name_idx
{
    source = host0_db0_source
    source = host0_db1_source
    source = host1_db0_source
    source = host1_db1_source
    #存放位置
    path = /usr/local/coreseek/var/data/product_name
    docinfo = extern
    charset_type = zh_cn.utf-8
    #Unigram dictionary路径,必须要有
    charset_dictpath = /usr/local/mmseg3/etc
    html_strip = 0
    #停止词
    stopwords = /usr/local/coreseek/dict/stopwords/stopwords.txt
}

indexer
{
    mem_limit = 128M
}

searchd
{
    port = 9351
    log = /usr/local/coreseek/var/log/search_product_name.log
    query_log = /usr/local/coreseek/var/query_product_name.log
    read_timeout = 5
    max_children = 30
    pid_file = /usr/local/coreseek/var/searchd_product_name.pid
    max_matches = 10000
    seamless_rotate = 1
    preopen_indexes = 0
    unlink_old = 1
}

6. 启动索引服务

./searchd -c /usr/local/coreseek/etc/sphinx.conf -i product_name_idx
## 查看进程、端口是否启动:
ps -ef|grep product_name_idx
netstat -na|grep 9351

停止该进程

./searchd -c /usr/local/coreseek/etc/sphinx.conf -i product_name_idx --stop

7. 建立索引

cd /usr/local/coreseek/bin
indexer -c {最好配置文件绝对路径} {索引名字}
在该实例中:
./indexer -c /usr/local/coreseek/etc/sphinx.conf product_name_idx

sphinx搜索引擎只会搜索string类型的字段,即sql_field_string类型的字段,如果想要搜索其他类型的字段,需要将此字段设为sql_field_string类型

8. 用search程序直接搜索

/usr/local/coreseek/bin/search -c {最好配置文件绝对路径} {索引名字}{搜索词}
在该实例中:
./search -c /usr/local/coreseek/etc/sphinx.conf -i product_name_idx 日本嗯

详细的用法参见./search

搜索时,可以用-s和-S的命令,如加上-s ‘fprice desc’ 就是按价格从大到小排序

注意,排序时应指定字段类型,否则默认都会按照字符串排序。
例如,如果按照int排序,则指定该字段类型为sql_attr_uint

9. 索引重建

./indexer -c /usr/local/coreseek/etc/sphinx.conf --rotate product_name_idx

10. 客户端

在下载的coreseek文件夹中有api文件夹,这里面有php,python,java的客户端。

Php的客户端只依赖于sphinxapi.php这个文件,只要把这个文件添加到项目,就可以直接运行。
Php的客户端最简单的例子是:

<?php
require ("sphinxapi.php");
header("Content-type:text/html;charset=utf-8");

$cl = new SphinxClient();
$cl->SetServer('192.168.144.163',9351);
$cl->SetMatchMode(SPH_MATCH_ALL);
$cl->SetArrayResult(true);
//设置返回结果集偏移量和数目
$cl->SetLimits(0, 40);
$cl->SetSortMode(SPH_SORT_EXTENDED, "fcomment_count desc");
//过滤Fseller_id=1的结果
$cl->setFilter('Fseller_id', array(1));
//过滤结果,返回Fprice在0-200的
$cl->setFilterFloatRange('Fprice', 0, 200);
$res = $cl->Query("外套","*");
print_r($res);
?>

猜你喜欢

转载自blog.csdn.net/okiwilldoit/article/details/78872290
今日推荐