Python+Sphinx+MYSQL
什么是Sphinx
sphinx是一款基于SQL的全文检索引擎,提供java、python、PHP、ruby等语言的API。可以基于数据库(如mysql)提供比数据库本身更优的全文检索服务。
安装Sphinx(Ubuntu)
1.首先需要安装MYSQL,MYSQL的安装这里不再赘述,网上教程很多.
2.直接到Sphinx官网下载对应的压缩包,下载之后,解压到/usr/local/文件夹下即可,这是免安装的压缩包.当然也可以去Github下载源码,使用源码进行安装.
使用源码安装的命令如下
#1.解压压缩包
$ tar xzvf sphinx-???.tar.gz
$ cd sphinx
#2.安装前的配置
./configure
--prefix, 用于指定安装位置,例如 --prefix=/usr/local/sphinx
--with-mysql, 当自动检测失败时,用于指定去哪里找MYSQL的依赖和库文件;
--with-static-mysql, 通过静态连接的MYSQL支持来构建Sphinx;
--with-pgsql, 用于说明哪里去找到PostgreSQL的依赖和库文件.
--with-static-pgsql, 通过静态连接的PostgreSQL支持来构建Sphinx;
#3.构建二进制文件
$ make
#4.安装
$ make install
下文中,我们将以来自官网的免安装版本进行部署和测试.
3.解压或者安装之后,在sphinx文件夹下会有一些子文件夹
api/ 存放着不同语言调用Sphinx的API,包括java,ruby,PHP,python
doc/ 存放着Sphinx的文档
etc/ sphinx配置文件,不同的索引可以写不同的配置文件
bin/ sphinx程序,其中有建立索引的程序:indexer, 搜索守护进程:searchd
var/ 一般用了放置indexer索引好的文件
让Sphinx可以工作的一个基本流程如下:
1.获取可执行文件(安装之后在bin/文件夹下).
2.创建sphinx.conf运行配置文件
3.执行一次indexer --all,来初始化索引.
4.运行searchd守护进程,用于监听检索.
5.执行查询.
6.定期执行indexer --all --rotate 来更新索引.
(看起来)So easy是不是,Let's go!.
运行官方测试样例
其中etc/文件夹下应该有三个文件:example.sql sphinx.conf.dist sphinx-min.conf.dist.它们是是Sphinx官方给出的样例配置文件.其中example.sql文件,用于在本地MYSQL中创建一个用于测试的数据库;sphinx.conf.dist是Sphinx启动的配置文件,而sphinx-min.conf.dist则是精简版的启动配置文件.
运行官方测试样例的步骤如下:
-
启动本地MySql服务,创建一个名为test的数据库(example.sql中指定的),然后执行example.sql脚本创建documents和tags两张表
-
因为我们对检索引擎没有什么特殊的需求,所以直接使用最简单的配置文件就行。直接使用sphinx-min.conf.dist做我们的配置文件,创建该文件的副本并更名为sphinx-min.conf,修改其中的mysql的host和user和password,如果是本地一数据库,官方建议host使127.0.0.1而非localhost。
这里附上一篇博客,专门讲Sphinx配置文件的. -
在sphinx安装路径下的bin文件夹下打开终端,以速度权限执行以下命令(如果是在windows系统下,要先以管理员权限打开CMD,然后再定位到bin文件夹下):
#这一条命令是用来根据conf文件创建文档的倒排索引的
./indexer -c ../etc/sphinx-min.conf --all
#索引创建成功之后,就可以启动检索引擎,监听端口9306和9312
./searchd -c ../etc/sphinx-min.conf
执行完这两条命令之后,searched进程就会以守护进程的形式开始工作,监听目标端口。其中9306端口是可以被mysql命令连接执行sphinxql(Sphinx的SQL)的,一般用于调试;而9312端口一般用来API调用。
- 下面我们尝试一下MySql连接9306端口,执行下面这条命令
mysql -h127.0.0.1 -P9306 -uroot -p
按照提示输入密码之后,就进入了经过Sphinx包装之后的“伪MySql”。我们执行下面这条SQL
show tables;
会看到test1和testrt两张“表”。这是由indexer创建的普通索引和增量索引。
我们再执行下面这条SQL
#这条SQL语句会返回test1表中所有与关键词"another"匹配的记录的id
#注意是单引号不是引号
select * from test1 where match('another');
返回结果是所有与another匹配的row的id列表。
在自己的数据库上运行Sphinx
- 启动本地MySql服务
- 编写sphinx配置文件:配置mysql的host、port、user、password。指定要检索的目标数据库sql_db。
这里要重点注意一下数据源中sql_query字段的配置,这个字段就是检索的基础,也是indexer创建索引的基础。sql_query是一条从目标数据表中查询指定字段的SQL语句,查询对象中必须包含至少一个唯一主键,否则无法建立索引。
并且sql_query这条配置将会决定Sphinx在哪些字段上建索引进行检索匹配,select的目标字段就是之后searchd进程进行关键字检索的对象。
其他配置项可以参考博客Sphinx配置文件详解来根据需要进行配置。
下面是一个最简单的配置文件样例,???处需要读者自行修改
#指定数据源
source src1
{
type = mysql
sql_host = ??????
sql_user = ?????
sql_pass = ?????
sql_db = ??????
sql_port = ????? # optional, default is 3306
sql_query = select * from pathway_entity
sql_query_info = select id, col from mytable where id = $id
}
#指定创建索引,注意这里指定的索引名称将会在之后的检索中被用到
index myindex
{
source = src1
path = /var/data/test1
}
index myrtindex
{
type = rt
rt_mem_limit = 128M
path = /var/data/testrt
rt_field = ????
rt_field = ????
}
indexer
{
mem_limit = 128M
}
searchd
{
listen = 9312
listen = 9306:mysql41
log = /var/log/searchd.log
query_log = /var/log/query.log
read_timeout = 5
max_children = 30
pid_file = /var/log/searchd.pid
seamless_rotate = 1
preopen_indexes = 1
unlink_old = 1
workers = threads # for RT to work
binlog_path = /var/data
}
- 建立索引并启动searchd进程:
#这一条命令是用来根据conf文件创建文档的倒排索引的
./indexer -c ../etc/sphinx-min.conf --all
#索引创建成功之后,就可以启动检索引擎,监听端口9306和9312
./searchd -c ../etc/sphinx-min.conf
- MySql连接9306端口,执行下面这条命令
mysql -h127.0.0.1 -P9306 -uroot -p
再执行下面这条SQL
#这条SQL语句会返回documents表中所有与关键词"another"匹配的记录的id
#注意是单引号不是引号
#这里的目标索引名,就是在配置文件中定义索引时指定的索引名
select * from 目标索引名 where match('关键字');
返回结果是所有与关键字匹配的row的id列表。注意,这里只返回主键。 在旧版本的Sphinx中,配置文件中数据源有个配置项名为sqp_query_info,可以用来返回多个字段,但是我在Sphinx3.1.1中测试该字段无效,已经过期。读者有兴趣可以自己测试一下。
- 通过API来调用Sphinx(PythonAPI)
我们这里只演示通过Python的API来调用,其他的语言类似,读者可以自己做尝试
在sphinx安装路径下的api文件夹中,有sphinxapi.py文件,需要读者引用
该文件。下面展示一个非常简单的demo。
from __future__ import print_function
from sphinxapi import *
import sys, time
#指定索引名称
#要与配置文件中创建索引时的索引名称一直
#使用 * 表示从所有索引中查找
index = 'myindex'
#指定过滤字段
filtercol = '????'
#指定将过滤字段的哪些值过滤掉(你可以理解为敏感词屏蔽类似的设计)
filtervals = []
#排序字段
sortby = '????'
#分组字段
groupby = '????'
groupsort = '@group desc'
limit = 0
#IP和port
host = '127.0.0.1'
port = 9312
#指定字段的权重,这些字段必须是在配置文件中的sql_query中出现的字段
#字段名 -权重 的形式,权重必须大于0,为整型
fieldWeights = {"pathway_name":100,"dms_description":5}
#q是要检索的关键字
q = 'this is a keyword'
# do query
cl = SphinxClient()
#设置自IP port
cl.SetServer ( host, port )
#设置过滤
if filtervals:
cl.SetFilter ( filtercol, filtervals )
if groupby:
cl.SetGroupBy ( groupby, SPH_GROUPBY_ATTR, groupsort )
if sortby:
cl.SetSortMode ( SPH_SORT_EXTENDED, sortby )
if limit:
cl.SetLimits ( 0, limit, max(limit,1000) )
#设置索引中字段的权重
if fieldWeights:
cl.SetFieldWeights(fieldWeights)
res = cl.Query ( q, index )
#以下用于输出检索的结果
if not res:
print('query failed: %s' % cl.GetLastError())
sys.exit(1)
if cl.GetLastWarning():
print('WARNING: %s\n' % cl.GetLastWarning())
print('Query \'%s\' retrieved %d of %d matches in %s sec' % (q, res['total'], res['total_found'], res['time']))
print('Query stats:')
if 'words' in res:
for info in res['words']:
print('\t\'%s\' found %d times in %d documents' % (info['word'], info['hits'], info['docs']))
if 'matches' in res:
n = 1
print('\nMatches:')
for match in res['matches']:
attrsdump = ''
for attr in res['attrs']:
attrname = attr[0]
attrtype = attr[1]
value = match['attrs'][attrname]
if attrtype==SPH_ATTR_TIMESTAMP:
value = time.strftime ( '%Y-%m-%d %H:%M:%S', time.localtime(value) )
attrsdump = '%s, %s=%s' % ( attrsdump, attrname, value )
print('%d. doc_id=%s, weight=%d%s' % (n, match['id'], match['weight'], attrsdump))
n += 1
本文介绍了在Ubuntu系统下如何使用Python、Sphinx和MySQL搭建全文搜索引擎。内容包括Sphinx的简介,安装步骤,运行官方测试样例,以及如何在自己的数据库上配置和运行Sphinx进行全文检索。

5363

被折叠的 条评论
为什么被折叠?



