最近负责一个项目,需要用到全文检索,我的环境大体如下:

 
    1、数据保存在MySQL中
    2、需要支持中文检索
    3、尽可能的简单
 
    选择了Sphinx,至于solr和Elasticsearch,看主页的介绍,它们对分布式、均衡等方面的支持非常好,只不过它们的安装包太大了,用起来挺不方便的,所以才放弃了它们,不过等有机会还可以研究一下。
 
    基本步骤如下:
   1、 安装:Sphinx的主页是http://sphinxsearch.com/,目前版本为2.2.8,下载界面为http://sphinxsearch.com/downloads/release/,分为32位和64位版本,还分为windows、debian/ubuntu,Fedora/Centos版本,也可以直接下载源代码,进行编译安装,我主要在windows上测试,在Centos上部署,简述过程如下
      1)Windows 8.1 X64 , sphinx 2.2.8 (Win64 binaries w/MySQL+PgSQL+libstemmer+id64 support)
      将压缩包解压缩到d:\blue下,解压缩后sphinx根目录为D:\blue\sphinx-2.2.8-release-win64-full。
      修改配置文件sphinx-min.conf.in,相对简单一下
#
# Minimal Sphinx configuration sample (clean, simple, functional)
#
#数据源,src1为名字,后面会引用这个名字
source src1
{
 type = mysql
 
 sql_host = localhost
 sql_user = test
 sql_pass =
 sql_db = test
 sql_port = 3306 # optional, default is 3306
 
 sql_query = \
  SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
  FROM documents
 
 sql_attr_uint = group_id
 sql_attr_timestamp = date_added
}
 
#test1为索引名称,sphinx检索时需要这个名字,相当于关系数据库中的table
index test1
{
 source = src1 #引用的数据源名称
 path = @CONFDIR@/data/test1
}
 
 
index testrt
{
 type = rt
 rt_mem_limit = 128M
 
 path = @CONFDIR@/data/testrt
 
 rt_field = title
 rt_field = content
 rt_attr_uint = gid
}
 
 
indexer
{
 mem_limit = 128M
}
 
 
searchd
{
 listen = 9312
 listen = 9306:mysql41
 log = @CONFDIR@/log/searchd.log
 query_log = @CONFDIR@/log/query.log
 read_timeout = 5
 max_children = 30
 pid_file = @CONFDIR@/log/searchd.pid
 seamless_rotate = 1
 preopen_indexes = 1
 unlink_old = 1
 workers = threads # for RT to work
 binlog_path = @CONFDIR@/data
}
       具体修改步骤如下,修改source src1下的mysql连接信息,包括主机、用户名、密码、数据库、端口,sql_query是数据源中的sql,这里是从mysql中抽取数据,sql_attr_*是用来分组排序用的,如果我们需要对一些字段进行排序操作,需要在这里定义,另外需要替换@CONFDIR@为你想要的目录,我的修改如下
#
# Minimal Sphinx configuration sample (clean, simple, functional)
#
 
source src1
{
 type = mysql
 
 sql_host = localhost
 sql_user = root
 sql_pass = 
 sql_db = sphinx
 sql_port = 3306 # optional, default is 3306
 
 sql_query = \
  SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
  FROM documents
 
 sql_attr_uint = group_id
 sql_attr_timestamp = date_added
 sql_query_pre = SET NAMES utf8
}
 
 
index test1
{
 source = src1
 path = D:/blue/sphinx_data/data/test1
 
 ngram_len = 1
 ngram_chars = U+4E00..U+9FBB, U+3400..U+4DB5, U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27, U+FA28, U+FA29, U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043, U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057, U+3059, U+305B, U+305D, U+305F, U+3061, U+3063, U+3066, U+3068, U+306A..U+306F, U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, U+3085, U+3087, U+3089..U+308E, U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7, U+30A9, U+30AD, U+30AF, U+30B3, U+30B5, U+30BB, U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB, U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3, U+30E5, U+30E7, U+30EE, U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5, U+31F6, U+31F7, U+31F8, U+31F9, U+31FA, U+31FB, U+31FC, U+31FD, U+31FE, U+31FF, U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C, U+A492..U+A4C6
 
}
 
 
index testrt
{
 type = rt
 rt_mem_limit = 128M
 
 path = D:/blue/sphinx_data/data/testrt
 
 rt_field = title
 rt_field = content
 rt_attr_uint = gid
}
 
 
indexer
{
 mem_limit = 128M
}
 
 
searchd
{
 listen = 9312
 listen = 9306:mysql41
 log = D:/blue/sphinx_data/log/searchd.log
 query_log = D:/blue/sphinx_data/log/query.log
 read_timeout = 5
 max_children = 30
 pid_file = D:/blue/sphinx_data/log/searchd.pid
 seamless_rotate = 1
 preopen_indexes = 1
 unlink_old = 1
 workers = threads # for RT to work
 binlog_path = D:/blue/sphinx_data/data
}
 
    修改的内容如黑体字所示,需要注意的是sql_query_pre, ngram_len,ngram_chars,这些都是支持中文检索必须的,如果没有的话,无法支持中文,另外将@CONFDIR@替换为d:\blue\sphinx_data,另外这个目录下建立两个目录data和log,不知道什么原因,系统无法自动创建这两个目录,会出错。
    另外在本机新建一个sphinx数据库,字符集选择utf-8,然后运行D:\blue\sphinx-2.2.8-release-win64-full下的example.sql,需要注意将其中的数据库前缀test.更换为sphinx.,表示在sphinx数据库中创建表,创建之后,在sphinx下检查一下,看是否存在documents和tags两张表。
    然后在D:\blue\sphinx-2.2.8-release-win64-full\bin下,运行indexer -c ..\sphinx-min.conf.in --all ,如下
D:\blue\sphinx-2.2.8-release-win64-full\bin>indexer -c ..\sphinx-min.conf.in --all
Sphinx 2.2.8-id64-release (r4942)
Copyright (c) 2001-2015, Andrew Aksyonoff
Copyright (c) 2008-2015, Sphinx Technologies Inc (http://sphinxsearch.com)
 
using config file '..\sphinx-min.conf.in'...
indexing index 'test1'...
collected 4 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4 docs, 33882 bytes
total 0.121 sec, 278900 bytes/sec, 32.92 docs/sec
skipping non-plain index 'testrt'...
total 3 reads, 0.000 sec, 12.0 kb/call avg, 0.0 msec/call avg
total 12 writes, 0.001 sec, 5.7 kb/call avg, 0.1 msec/call avg
需要注意的是,如果需要建立的索引已经被使用,即已经启动了searchd服务,就需要增加--rotate参数,类似于
indexer -c ..\sphinx-min.conf.in --all --rotate

然后在同一目录下运行 searchd -c ..\sphinx-min.conf.in,如下

D:\blue\sphinx-2.2.8-release-win64-full\bin>searchd -c ..\sphinx-min.conf.in
Sphinx 2.2.8-id64-release (r4942)
Copyright (c) 2001-2015, Andrew Aksyonoff
Copyright (c) 2008-2015, Sphinx Technologies Inc (http://sphinxsearch.com)
 
using config file '..\sphinx-min.conf.in'...
listening on all interfaces, port=9312
listening on all interfaces, port=9306
precaching index 'test1'
rotating index 'test1': success
precaching index 'testrt'
precached 2 indexes in 0.045 sec

没有什么错误,需要注意的是,需要先创建索引,才能启动服务,否则可能会出错,searchd命令也可以安装为服务,以后使用起来会更加方便,这里这么做也是为了看到底是否配置成功,否则系统服务出错,我们看不到错误原因。

    查看searchd的输出或者sphinx-min.conf.in的searchd的配置项,可以知道sphinx在两个端口监听,9312,9306,其中9312是Sphinx API访问的端口,9306是SphinxQL的,SphinxQL是一个Mysql接口,可以通过mysql客户端访问。
2、SphinxQL
     SPihinxQL是一种mysql接口,可以通过sql语句来执行查询,可以用mysql命令行工具,也可以使用mysql的客户端工具,如HeidiSQL,这个是我常常使用的mysql客户端,配置连接很简单,用户名密码不用填,只要设置主机和端口就可以了,端口通常为9306,命令行如下
     >mysql -h localhost -P9306
     下面就可以使用SphinxQL了
     mysql中的数据如下
id group_id group_id2 date_added title content
1 1 5 2015/3/27 16:53 test one this is my test document number one. also checking...
2 1 6 2015/3/27 16:53 test two this is my test document number two
3 2 7 2015/3/27 16:53 another doc this is another group
4 2 8 2015/3/27 16:53 doc number four this is to test groups
   运行SphinxQL,
  mysql> select * from test1 where match('my');
+------+----------+------------+
| id   | group_id | date_added |
+------+----------+------------+
|    1 |        1 | 1427446411 |
|    2 |        1 | 1427446411 |
+------+----------+------------+
2 rows in set (0.00 sec)
     可以看出这里面并不包含数据,只包含数字字段:id和group_id,所以如果想得到数据,需要在mysql中重新查询数据才能得到结果。
     下面修改一下数据,改成中文,如下
id group_id group_id2 date_added title content
1 1 5 2015/3/27 16:53 test one this is my test document number one. also checking...
2 1 6 2015/3/27 16:53 test two this is my test document number two
3 2 7 2015/3/27 16:53 another doc 代码到了一定时间,必须重构,否则会出现问题
4 2 8 2015/3/27 16:53 doc number four 重庆制造到了最后阶段了,车体构造已经完成,就等待最后的出厂了
      重新生成索引,
      D:\blue\sphinx-2.2.8-release-win64-full\bin>indexer -c ..\sphinx-min.conf.in --all --rotate
 

Sphinx 2.2.8-id64-release (r4942)

 

Copyright (c) 2001-2015, Andrew Aksyonoff

 

Copyright (c) 2008-2015, Sphinx Technologies Inc (http://sphinxsearch.com)

 
 

using config file '..\sphinx-min.conf.in'...

 

indexing index 'test1'...

 

collected 4 docs, 0.0 MB

 

sorted 0.0 Mhits, 100.0% done

 

total 4 docs, 303 bytes

 

total 0.086 sec, 3518 bytes/sec, 46.44 docs/sec

 

skipping non-plain index 'testrt'...

 

total 3 reads, 0.000 sec, 0.4 kb/call avg, 0.0 msec/call avg

 

total 12 writes, 0.001 sec, 0.2 kb/call avg, 0.0 msec/call avg

 

rotating indices: successfully sent SIGHUP to searchd (pid=4556).

 
     中文查询就无法在mysql命令行中执行了,这是在windows的情况下,因为其中文字符不是UTF-8,会出现无法搜索出结果的现象,需要用HeidiSQL之类的,运行查询,
     select * from test1 where match('重构');
"id" "group_id" "date_added"
"3" "2" "1427446411"
"4" "2" "1427446411"

这里面有一个问题,可以看出id 4实际上并没有“重构”这个词,只是包含“重”“构”这两个字而已,所以可能无法满足某些需求,但是好在Sphinx的默认匹配方式是短语相似度,所以理论上来说,包含“重构”这个词的会排序在前面,简单测试也是如此,是否一直如此就不知道了。可以参考这篇文章:http://rainkid.blog.163.com/blog/static/165140840201010277223611/

3、Nodejs查询Sphinx
   1)Sphinxapi
        首页在https://github.com/lindory-project/node-sphinxapi/tree/master,安装方式: npm install sphinxapi
        文档比较详细,简单实用如下
        #sphinx2.js
var SphinxClient = require ("sphinxapi"),
    util = require('util'),
    assert = require('assert');
 
var cl = new SphinxClient();
cl.SetServer('localhost', 9312);
cl.Query('重构','test1', function(err, result) {
        assert.ifError(err);
        console.log(util.inspect(result, false, null, true));
});
运行程序,node sphinx2.js,如下
{ error: '',
  warning: '',
  status: [ 0 ],
  fields: [ 'title', 'content' ],
  attrs:
   [ [ 'group_id', 1 ],
     [ 'date_added', 2 ] ],
  matches:
   [ { id: 3,
       weight: 2,
       attrs: { group_id: 2, date_added: 1427446411 } },
     { id: 4,
       weight: 1,
       attrs: { group_id: 2, date_added: 1427446411 } } ],
  total: 2,
  total_found: 2,
  time: 0.004,
  words:
   [ { word: '重', docs: 2, hits: 2 },
     { word: '构', docs: 2, hits: 2 } ] }
可以看出和SphinxQL运行的效果一样,只不过返回的信息更多而已。

2)SphinxQL

       SphinxQL需要SphinxAPI的支持,所以在安装sphinxapi包的基础上,还需要安装node-mysql包,命令为npm install mysql
       简单例子如下
#sphinx.js
var mysql = require('mysql');
 
var connection = mysql.createConnection(
    {
      host      : 'localhost',
      port : '9306'
    }
);
 
connection.connect();
 
var queryString = "SELECT * FROM test1 WHERE MATCH('重构')";
 
connection.query(queryString, function(err, rows, fields) {
    if (err) throw err;
 
    for (var i in rows) {
        console.log(JSON.stringify(rows[i]));
    }
});
 
connection.end();
 
运行程序,node sphinx.js,如下
{"id":3,"group_id":2,"date_added":1427446411}
{"id":4,"group_id":2,"date_added":1427446411}
 
乍看起来,似乎sphinxapi提供的信息更多,我没有具体比较过,不过sphinxQL也包含了一些函数,如weight(),可以返回权重,如执行SELECT *, weight() FROM test1 WHERE MATCH('重构'); 结果如下
"id" "group_id" "date_added" "weight()"
"3" "2" "1427446411" "2557"
"4" "2" "1427446411" "1557"
可知sphinxap提供的权重,似乎是sphinxQL提供的值除以1000之后的值

3、CentOS的安装和使用

       CentOS的使用没什么特别的,最好是下载rpm安装包,过程如下
$ yum install postgresql-libs unixODBC
$ rpm -Uhv sphinx-2.2.8.rhel6.x86_64.rpm
$ service searchd start
具体的使用和Windows是一样的,没有什么区别。

4、其他

        1)最好的文档来源是官方文档,比较详细,内容也较多
        2)如果对信息的实时性要求较高,可以使用实时索引,具体内容我没有仔细研究过,以后有机会研究吧
        3)索引合并,如果原数据较多,新增加的数据不多,可以采用增量更新索引的办法,命令如下
indexer --merge DSTINDEX SRCINDEX [--rotate]
        srcindex会更新到dstindex上,如果目标索引正在使用,需要使用--rotate参数
        需要注意的是,如果发生重复现象,原始索引的数据并不会删除,如果要达到这一目的,可以运行
indexer --merge main delta --merge-dst-range deleted 0 0
        在某些情况下,这种方式较为有用,如每隔一小时合并一次索引,晚上重建一次索引,如果数据规模过大,就需要考虑分布式了,这个问题就比较复杂了,需要另外研究了。
        4)sql_query_pre = SET NAMES utf8 
         这个设置有些奇怪,我在文档中并没有查到这个信息,,但是不设置这个,就无法生成中文索引,后来还是在sphinx群中咨询了一下,“熊熊熊熊”同学看了我的配置文件,指出了这个问题,我才得以继续使用sphinx,否则我都要放弃sphinx了,这里要对“熊熊熊熊”同学表示感谢。不知道是不是windows 8的原因,不过在linux下也需要设置这个参数,不知道为什么。
       5)安装为服务(windows 8. 1)
        RPM和DEB包自动安装服务,在windows下,需要运行seachd命令将其安装为服务:
     searchd --install -c D:\blue\sphinx-for-chinese-2.2.1-dev-r4311-win32\sphinf-min.conf.in 服务名
        如果不指定服务名,会在windows服务列表中生成一个名为search的服务。
        在测试时,最好用searchd命令行运行,不要安装为服务,因为没有输出会比较麻烦,出了问题不好解决。
        删除服务: sc delete 服务名
  5、sphinx for chinese的配置问题(windows 8.1)
       sphinx for chinese的版本有点旧了,最新的如下
        其使用方式也比较简单,需要在配置文件中修改索引项,如下
index test1
{
 source = src1
 path = D:/blue/sphinx_data/data/test1
 docinfo = extern
 charset_type = utf-8
 chinese_dictionary = D:\blue\sphinx-for-chinese-2.2.1-dev-r4311-win32\xdict
}
其中charset_type = utf-8在最新的版本中已经废弃,因为默认已经是utf-8,xdict是一个字典文件
        xdict是一个字典文件,可以从https://sphinx-for-chinese.googlecode.com/files/xdict_1.1.tar.gz下载,然后解压缩,用mkdict命令生成字典,如下:bin\mkdict.exe xdict_1.1.txt xdict
      Sphinx for chinese用起来也很方便,但是有一个不一样的地方,还是使用上面的数据,运行SphinxQL,
      select *,weight() from test1 where match('重构');
      "id" "group_id" "date_added" "weight()"
      "3" "2" "1427446411" "1695"
      可以看出这次可以精确找到id为3的数据,没有搜索到4,但是如果只搜索单字“重”,是没有数据的,这是不一样的地方。
     
 
       
       
     

Sphinx学习笔记(一)的更多相关文章

  1. Sphinx学习笔记2

    因为网站搜索的需要,启动了一个搜索引擎项目,其实也算不上完整的搜索引擎,需求很简单,如下:     1)搜索产品名.类别名.品牌名.副标题.关键字等字段     2)数据量目前为13000左右,未来可 ...

  2. SQL反模式学习笔记17 全文搜索

    目标:全文搜索 使用SQL搜索关键字,同时保证快速和精确,依旧是相当地困难. SQL的一个基本原理(以及SQL所继承的关系原理)就是一列中的单个数据是原子性的. 反模式:模式匹配 使用Like 或者正 ...

  3. Linux学习笔记-Linux系统简介

    Linux学习笔记-Linux系统简介 UNIX与Linux发展史 UNIX是父亲,Linux是儿子. UNIX发行版本 操作系统 公司 硬件平台 AIX IBM PowerPC HP-UX HP P ...

  4. python学习笔记:建立一个自己的搜索引擎

    写学习笔记是我学习python以来养成的一个习惯,每学习一个知识点,便整理成文字记录下来.搜索引擎大家经常都有在使用,国内外也很很多搜索引擎平台. Google搜索引擎建立至今已经快20年了,之后全球 ...

  5. 《SQL 反模式》 学习笔记

    第一章 引言 GoF 所著的的<设计模式>,在软件领域引入了"设计模式"(design pattern)的概念. 而后,Andrew Koenig 在 1995 年造了 ...

  6. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  7. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  8. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  9. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

随机推荐

  1. 【python】python的正则表达式 re

    ps:本文摘自互联网,觉得结构很好,讲的也很清晰.记下,备查. 延伸阅读:python的 内建函数 和 subprocess .此文是本系列的第三篇文章了,和之前一样,内容出自官方文档,但是会有自己的 ...

  2. Winwos Server 2012发布ASP.NET MVC5 项目

    一.本文实验环境: Windows Server 2012 R2 Visual Studio 2015 项目为:ASP.NET MVC 5.0,使用的是SQL SERVER 2008 R2数据库 二. ...

  3. Struts2-046验证脚本

    下面分享一下Struts2-046验证的python脚本 #encoding:utf-8 import urllib2 from poster.encode import multipart_enco ...

  4. 为什么我的子线程更新了 UI 没报错?借此,纠正一些Android 程序员的一个知识误区

    开门见山: 这个误区是:子线程不能更新 UI ,其应该分类讨论,而不是绝对的. 半小时前,我的 XRecyclerView 群里面,一位群友私聊我,问题是: 为什么我的子线程更新了 UI 没报错? 我 ...

  5. input取值区间实例

    前端开发中经常会遇到 input 取值区间的需求,比如搜索的时候,价格区间,积分值区间 大致的需求为 input 的值必须是正整数,第二个 input 的值必须大于第一个 DOM结构如下: <d ...

  6. Nova控制节点集群

    #Nova控制节点集群 openstack pike 部署 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html ##Nova控制节点集群 # control ...

  7. mysql 系统性浅聊 myisam 存储引擎【原创】

    >>思维导图 >>介绍 mysql中的存储引擎都是以插件的形式存在,目前用的最多存储引擎就是innodb和myisam.MySQL5.5.5以后(包括5.5.5)默认使用Inn ...

  8. CCF-201604-1-折点计数

    问题描述 试题编号: 201604-1 试题名称: 折点计数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 给定n个整数表示一个商店连续n天的销售量.如果某天之前销售量在增长 ...

  9. 用echartsjs 实现动态绘制折线、柱状等图形,并实现多图联动效果

    echarts对于大数据处理后绘制折线图,柱形图等等的效果和速度都很好.下面我们介绍 怎么把封装的数据列表解析出来,动态绘图,并且实现鼠标联动效果引入js文件: <script type=&qu ...

  10. git学习资料包

    1.廖雪峰老师的git教程:https://www.liaoxuefeng.com    -----点击“GIT教程”开始学习 2.菜鸟教程git学习:http://www.runoob.com/gi ...