Ubuntu下,Python+Sphinx+MYSQL搭建搜索引擎

本文介绍了在Ubuntu系统下如何使用Python、Sphinx和MySQL搭建全文搜索引擎。内容包括Sphinx的简介,安装步骤,运行官方测试样例,以及如何在自己的数据库上配置和运行Sphinx进行全文检索。

什么是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则是精简版的启动配置文件.
运行官方测试样例的步骤如下:

  1. 启动本地MySql服务,创建一个名为test的数据库(example.sql中指定的),然后执行example.sql脚本创建documents和tags两张表

  2. 因为我们对检索引擎没有什么特殊的需求,所以直接使用最简单的配置文件就行。直接使用sphinx-min.conf.dist做我们的配置文件,创建该文件的副本并更名为sphinx-min.conf,修改其中的mysql的host和user和password,如果是本地一数据库,官方建议host使127.0.0.1而非localhost。
    这里附上一篇博客,专门讲Sphinx配置文件的.

  3. 在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调用。

  1. 下面我们尝试一下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

  1. 启动本地MySql服务
  2. 编写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
}
  1. 建立索引并启动searchd进程:
#这一条命令是用来根据conf文件创建文档的倒排索引的
./indexer -c ../etc/sphinx-min.conf --all
#索引创建成功之后,就可以启动检索引擎,监听端口9306和9312
./searchd -c ../etc/sphinx-min.conf
  1. 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中测试该字段无效,已经过期。读者有兴趣可以自己测试一下。

  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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值