精华内容
参与话题
问答
  • sphinx

    千次阅读 2018-01-12 00:46:19
    sphinx是一个独立的搜索引擎,为其他应用提供高速、低空间占用、高结果相关度的全文搜索功能。sphinx可以非常容易的与sql数据库和脚本语言集成。 搜索api支持php、python、perl、ruby和java,并且也可以用作mysql...

    一、Introduction

    sphinx是一个独立的搜索引擎,为其他应用提供高速、低空间占用、高结果相关度的全文搜索功能。sphinx可以非常容易的与sql数据库和脚本语言集成。

    搜索api支持php、python、perl、ruby和java,并且也可以用作mysql存储引擎。

    coreseek全文检索服务器2.0是在sphinx基础上开发的全文检索软件,按照GPLv2协议发行。中文版的sphinx。

    sphinx的特性,高速建立索引,高性能的搜索,处理海量数据,优秀的相关度算法,支持分布式搜索,可作为mysql存储引擎提供搜索服务,支持布尔、短语、词语相似度等多种检索模式等等。

    支持多数操作系统。

    二、windows下使用sphinx

    一般的搜索中,使用关键字搜索时一般是使用like  ‘%xxx%’,这样查询在数据量大时非常慢,like是全表扫描。

    到coreseek官网下载软件包解压。

    1.        使用sphinx为要搜索的数据创建全文索引

    制作配置文件,在解压包的etc/下,复制一份csft_mysql.conf,改名为sphinx.conf,放到解压包的根目录/下。修改配置文件。

    #MySQL数据源配置,详情请查看:http://www.coreseek.cn/products-install/mysql/
    
    #源定义,为eshopphp数据库中的es_goods表为数据源
    
    source goods
    
    {
    
        type                    = mysql
    
    
    
        sql_host                = localhost
    
        sql_user                = root
    
        sql_pass                = 123456
    
        sql_db                  = eshopphp
    
        sql_port                = 3306
    
        sql_query_pre            = SET NAMES utf8
    
        #主查询,要为哪些数据建索引就使用一条sql语句把这些数据取出来
    
        #第一个字段一定要求是id
    
        #为所有的商品的goods_name,goods_desc,attr_value这三个字段创建全文索引
    
        sql_query                = SELECTa.id,a.goods_name,a.goods_desc,GROUP_CONCAT(b.attr_value) attr_value  FROM es_goods a left join es_goods_attr b ona.id=b.goods_id group by a.id
    
    }
    
    
    
    #index定义,一个数据源对应一个index
    
    #定义索引文件
    
    index goods
    
    {
    
        source          = goods             #对应的source名称
    
        #生成的索引文件存放的目录\索引文件的名字,不要中文路径,下面最后的goods为索引文件的名字
    
        path            = D:\002php\shpinx\var\data\goods
    
        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/mmseg3/etc/#BSD、Linux环境下设置,/符号结尾
    
        #Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...
    
        charset_dictpath = D:\002php\shpinx\etc
    
        #shpinx只支持utf-8
    
        charset_type     = zh_cn.utf-8
    
    }
    
    
    
    #全局index定义
    
    indexer
    
    {
    
        mem_limit            = 128M
    
    }
    
    
    
    #searchd,sphinx服务器配置
    
    searchd
    
    {
    
        listen              =   9312
    
        read_timeout        = 5
    
        max_children        = 30
    
        max_matches         = 1000
    
        seamless_rotate     = 0
    
        preopen_indexes     = 0
    
        unlink_old          = 1
    
        #配置以下三个文件存放的绝对路径,目录中不要出现中文
    
        pid_file =D:\002php\shpinx\var\log\searchd_mysql.pid
    
        log =D:\002php\shpinx\var\log\searchd_mysql.log
    
        query_log = D:\002php\shpinx\var\log\query_mysql.log
    
    }

    使用sphinx为商品数据生成索引

    使用bin/indexer.exe命令。

    indexer.exe -c  D:\002php\shpinx\sphinx.conf  goods

    2.        安装并启动sphinx服务器

    使用bin/searchd.exe命令

    searchd.exe -c  D:\002php\shpinx\sphinx.conf  --install

    打开windows服务窗口找到sphinx并启动

    执行services.msc打开服务窗口。

    3.        在项目中使用php代码查询sphinx

    先复制sphinx的api目录下的sphinxapi.php文件到项目

    然后在关键字搜索的方法中调用sphinx的客户端类。

        //接收要搜索的关键
    
        $key = I('get.key');
    
        //搜索sphinx
    
        require ('./sphinxapi.php');
    
        $sph = new \SphinxClient();
    
        $sph->SetServer('localhost', 9312);
    
        //第二个参数,sphinx中索引的名字默认是*,表示所有的索引
    
    $ret =$sph->Query($key, 'goods');

    sphinx的返回结果中会返回符合条件的id,不会返回关于这个商品的具体数据,然后通过数据库取出商品的详细信息。

    三、sphinx的实时索引更新

    如果整个数据量非常大,以至于难以经常性的重建索引,但是每次新增的记录却相对来说少。比如,一个论坛有100000000000个已经归档的帖子,但是每天只有1000个新帖子。这中情况下使用主索引+增量索引(main+delta)模式来实现近实时的索引更新。

    这种方法的基本思路是设置两个数据源和两个索引,对很少更新或根本不更新的数据建立主索引,而对新增文档建立增量索引。在上述例子中,那个量大的已经归档的帖子们放在主索引中,而每天新增的1000个帖子放在新增索引中。增量索引更新的频率可以非常快,而文档可以在出现几分钟内就可以检索到。

    比如商城中,后添加的商品在sphinx中无法搜索出来,必须要重新创建索引。如果数据量非常大,有10000000件商品,每天新添加100个商品,每天都要为所有的商品重新索引。

    实现步骤

    1.        创建一张表

    用于保存已经创建好索引的商品的最大id。根据这个id找出哪些商品没有创建索引。每次创建好索引后把最大的id存进去,定期取出新的商品创建新增索引,创建完新的索引再把最大的id更新到这个表。

    create tablees_sphinx_id(
    
             id mediumint unsigned not null default'0' comment '已经创建好索引的最后一件商品的id'
    
    )engine=innodbdefault charset=utf8 comment 'sphinx';
    
    insert intoes_sphinx_id values(0);

    2.        修改sphinx配置文件

    创建好索引后把已经建好的最后的商品id更新到这个表。

    #源定义,为eshopphp数据库中的es_goods表为数据源
    
    source goods
    
    {
    
        type                    = mysql
    
    
    
        sql_host                = localhost
    
        sql_user                = root
    
        sql_pass                = 123456
    
        sql_db                 = eshopphp
    
        sql_port                = 3306
    
        sql_query_pre           = SET NAMES utf8
    
        #主查询,要为哪些数据建索引就使用一条sql语句把这些数据取出来
    
        #第一个字段一定要求是id
    
        #为所有的商品的goods_name,goods_desc,attr_value这三个字段创建全文索引
    
        sql_query       = SELECT a.id,a.goods_name,a.goods_desc,GROUP_CONCAT(b.attr_value)attr_value  FROM es_goods a left joines_goods_attr b on a.id=b.goods_id group by a.id
    
        #在创建好索引后最后一个商品id更新到表中
    
        sql_query_post          = update es_sphinx_id set id= (selectmax(id) from es_goods where is_on_sale='是')
    
    }

    关闭sphinx,重新创建商品索引。再启动sphinx服务。

    3.        修改配置文件,为后添加的没有创建索引的数据生成一个增量索引

    在配置文件中为增量索引创建数据源和索引文件的配置

    #后添加的还没有索引的数据的数据源
    
    source goods_new
    
    {
    
        type                    = mysql
    
        sql_host                = localhost
    
        sql_user                = root
    
        sql_pass                = 123456
    
        sql_db                  = eshopphp
    
        sql_port                = 3306
    
        sql_query_pre           = SET NAMES utf8
    
        #取出后添加的还没有建索引的商品
    
        sql_query               = SELECTa.id,a.goods_name,a.goods_desc,GROUP_CONCAT(b.attr_value) attr_value  FROM es_goods a left join es_goods_attr b ona.id=b.goods_id where a.is_on_sale='是' and a.id > (select id from es_sphinx_id) group by a.id
    
        #在创建好索引后最后一个商品id更新到表中
    
        sql_query_post          = update es_sphinx_id set id= (selectmax(id) from es_goods where is_on_sale='是')
    
    }
    
    
    
    #定义新创建的数据源的索引文件
    
    index goods_new
    
    {
    
        source          = goods_new             #对应的source名称
    
        #生成的索引文件存放的目录\索引文件的名字,不要中文路径,下面最后的goods为索引文件的名字
    
        path            =D:\002php\shpinx\var\data\goods_new
    
        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/mmseg3/etc/#BSD、Linux环境下设置,/符号结尾
    
        #Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...
    
        charset_dictpath = D:\002php\shpinx\etc
    
        #shpinx只支持utf-8
    
        charset_type     = zh_cn.utf-8
    
    }

    4.        编写脚本处理增量索引

    先为增量索引生成索引文件;把新生成的增量的索引文件合并到主索引文件。

    windows系统是bat脚本,*.bat。

    linux系统的是shell脚本,只要有可执行的权限就可以执行。

    比如在项目的根目录下创建updateNewSphinxGoods.bat

    D:\002php\shpinx\bin\indexer.exe  -c D:\002php\shpinx\sphinx.conf goods_new
    
    D:\002php\shpinx\bin\indexer.exe  -c D:\002php\shpinx\sphinx.conf --merge  goods  goods_new --rotate

    --rotate是为了便于在sphinx服务器运行期间执行合并的命令,否则goods被锁无法执行。

    双击脚本执行。为了便于关于观察执行过程和结果,也可以拖到cmd黑窗口执行。

    添加了新的商品之后只要执行这个脚本就可以在sphinx中搜索到了。但是每次都手动执行这个脚本太麻烦了,可以配置这个脚本每隔一段时间自动执行一次。

    5.        配置脚本自动执行

    如果是windows系统,windows—>管理工具--> 任务计划程序-- >创建基本任务,创建完成后在右键这个任务,选择属性,点击触发器,新建,设置为一次,重复任务间隔为5分钟,持续时间为无限期。

    如果是linux系统,配置crond进程。

    四、修改数据库数据时更新sphinx

    当修改了数据库中的数据时,sphinx中已经生成的索引并没有更新,所以使用修改前的关键字还是能搜索出可能不符合条件的商品,这就需要在修改商品时把sphinx中的索引也一起更新。

    思路是,只能为修改了的商品重新创建索引并合并到主索引上,在合并之前先删除原索引。

    1.        在创建索引时必须找出该修改了的数据。

    修改商品表添加一个字段,is_updated,默认值是0,一旦被修改了就设置为1。然后定期让sphinx把is_updated=1的重新创建索引。

    is_updated  tinyint  unsigned  not  null  default '0'  comment  '是否被修改',

    然后,修改商品模型,当修改商品时,将这个字段更新为1。

    2.        修改sphinx的配置文件,为修改的商品重建索引

    #后添加的还没有索引的数据或者修改过的商品的数据源
    
    source goods_new
    
    {
    
        type                    = mysql
    
        sql_host                = localhost
    
        sql_user                = root
    
        sql_pass                = 123456
    
        sql_db                  = eshopphp
    
        sql_port                = 3306
    
        sql_query_pre           = SET NAMES utf8
    
        #取出后添加的还没有建索引的商品
    
        sql_query               = SELECTa.id,a.goods_name,a.goods_desc,GROUP_CONCAT(b.attr_value) attr_value  FROM es_goods a left join es_goods_attr b ona.id=b.goods_id where a.is_on_sale='是' and (a.id > (select id from es_sphinx_id) or a.is_updated=1)group by a.id
    
        #在创建好索引后最后一个商品id更新到表中
    
        sql_query_post          = update es_sphinx_id set id= (selectmax(id) from es_goods where is_on_sale='是')
    
       
    
    }

    3.        修改搜索的php代码让sphinx先过滤掉被标记为修改的,只放行is_updated为0的

        //过滤掉被标记为修改的
    
        $sph->SetFilter('is_updated', array(0);

    4.        然后在sphinx中定义is_updated为一个属性

    首先要取出这个字段,然后才可定义为一个属性。同时将获取is_updated段时将这个字段固定为0。

    主索引和增量索引都要添加这个属性,否则在merge主索引和增量索引时将失败。

    #########################主索引的数据源与索引配置#######################
    
    #源定义,为eshopphp数据库中的es_goods表为数据源
    
    source goods
    
    {
    
        type                    = mysql
    
    
    
        sql_host                = localhost
    
        sql_user                = root
    
        sql_pass                = 123456
    
        sql_db                  = eshopphp
    
        sql_port                = 3306
    
        sql_query_pre           = SET NAMES utf8
    
        #主查询,要为哪些数据建索引就使用一条sql语句把这些数据取出来
    
        #第一个字段一定要求是id
    
        #为所有的商品的goods_name,goods_desc,attr_value这三个字段创建全文索引
    
       sql_query               = SELECTa.id,0 is_updated,a.goods_name,a.goods_desc,GROUP_CONCAT(b.attr_value)attr_value  FROM es_goods a left joines_goods_attr b on a.id=b.goods_id where a.is_on_sale='是' group by a.id
    
        #在创建好索引后最后一个商品id更新到表中
    
        sql_query_post          = update es_sphinx_id set id= (selectmax(id) from es_goods where is_on_sale='是')
    
    
    
        #把一个字段的值定义为一个属性,属性可以用来过滤、排序
    
        sql_attr_uint           = is_updated
    
    }
    
    
    
    #后添加的还没有索引的数据或者修改过的商品的数据源
    
    source goods_new
    
    {
    
        type                    = mysql
    
        sql_host                = localhost
    
        sql_user                = root
    
        sql_pass                = 123456
    
        sql_db                  = eshopphp
    
        sql_port                = 3306
    
        sql_query_pre           = SET NAMES utf8
    
        #取出后添加的还没有建索引的商品
    
       sql_query               = SELECTa.id,0 is_updated,a.goods_name,a.goods_desc,GROUP_CONCAT(b.attr_value)attr_value  FROM es_goods a left joines_goods_attr b on a.id=b.goods_id where a.is_on_sale='是' and (a.id > (select id from es_sphinx_id) or a.is_updated=1)group by a.id
    
        #在创建好索引后最后一个商品id更新到表中
    
        sql_query_post          = update es_sphinx_id set id= (selectmax(id) from es_goods where is_on_sale='是')
    
        #把一个字段的值定义为一个属性,属性可以用来过滤、排序
    
        sql_attr_uint           = is_updated
    
    }

    由于修改了配置文件,所以要重建索引。

    D:\002php\shpinx\bin>indexer.exe  -c D:\002php\shpinx\sphinx.conf goods --rotate

    5.        然后,在商品模型中,修改一件商品后要把sphinx中这件商品的is_updated属性设置成1。

    //设置sphinx中的这条记录的is_updated属性为1
    
    //搜索sphinx
    
    require('./sphinxapi.php');
    
    $sph = new\SphinxClient();
    
    $sph->SetServer('localhost',9312);
    
    //把id=$id这件商品的is_updated属性更新为1
    
    $sph->UpdateAttributes('goods',array('is_updated'),array($id=>array(1)));

    6.        删除旧的索引

    旧的索引仍然在sphinx的索引文件中,应该定期的把is_updated=1的删掉。删除旧的索引时需要使用indexer.exe   --merge dst  src  --merge-dst-range  [attr] [min]  [max]  [attr] [min]  [max]命令。这个命令的意思是合并dst索引和src索引,在合并前先过滤dst索引中属性值在min和max(包含max)之间的索引,这个过滤条件可以设置多个。由于必须需要两个索引合并才能实现对dst索引的过滤,也就是案例中对goods索引的过滤,以实现删除is_updated值为1的旧索引。所以,创建要删除的索引的数据源和索引配置 goods_del。为了保证合并时不报错,goods_new索引文件的字段要和goods的保持一致。创建goods_del的数据源和索引配置时需复制goods的。配置时将is_updated固定为1,以便合并后能够将要删除的索引在goods主索引中标记出,即其is_updated为1。由于- -merge-dst-range和- -merge的执行可能是异步的。为了保证过滤的成功,再合并goods_new索引时进行过滤。

    #########################要删除的商品的数据源与索引配置#######################
    
    #要删除的商品的数据源
    
    source goods_del
    
    {
    
        type                    = mysql
    
        sql_host                = localhost
    
        sql_user                = root
    
        sql_pass                = 123456
    
        sql_db                  = eshopphp
    
        sql_port                = 3306
    
        sql_query_pre           = SET NAMES utf8
    
        #取出后添加的还没有建索引的商品
    
        sql_query               = SELECT a.id,1 is_updated,a.goods_name,a.goods_desc,GROUP_CONCAT(b.attr_value)attr_value  FROM es_goods a left joines_goods_attr b on a.id=b.goods_id where a.is_on_sale='是' and a.is_updated=1 group by a.id
    
       
    
        #把一个字段的值定义为一个属性,属性可以用来过滤、排序
    
        sql_attr_uint           = is_updated
    
    }
    
    
    
    #定义新创建的数据源的索引文件
    
    index goods_del
    
    {
    
        source          = goods_del             #对应的source名称
    
        #生成的索引文件存放的目录\索引文件的名字,不要中文路径,下面最后的goods为索引文件的名字
    
        path            =D:\002php\shpinx\var\data\goods_del
    
        docinfo         = extern
    
        mlock           = 0
    
        morphology      = none
    
        min_word_len    = 1
    
        html_strip      = 0
    
    
    
        #中文分词配置,中文分词词库文件所在目录,详情请查看:http:src="__PUBLIC__/Home/images/www.coreseek.cn/products-install/coreseek_mmseg/
    
        #charset_dictpath = /usr/local/mmseg3/etc/#BSD、Linux环境下设置,/符号结尾
    
        #Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...
    
        charset_dictpath = D:\002php\shpinx\etc
    
        #shpinx只支持utf-8
    
        charset_type     = zh_cn.utf-8
    
    }

    7.        然后修改脚本文件,加入合并时的过滤条件

    ::--merge-dst-range表示在合并时过滤,但是合并时未必已经将is_updated为1的商品合并到goods索引主表中

    ::所以可能是先过滤了然后合并的,这导致没有将is_updated为1的商品索引从goods索引中过滤掉,为了妥善

    ::分开执行,先将要过滤的商品索引一起合并到goods主索引,然后在后面合并goods_new时做过滤,删除is_updated为1的索引

    ::合并时只保存is_updated=0其他的属性值的索引都过滤掉

    D:\002php\shpinx\bin\indexer.exe  -c D:\002php\shpinx\sphinx.conf goods_del  --rotate
    
    D:\002php\shpinx\bin\indexer.exe  -c D:\002php\shpinx\sphinx.conf --merge  goods  goods_del --rotate
    
    D:\002php\shpinx\bin\indexer.exe  -c  D:\002php\shpinx\sphinx.conf  goods_new --rotate
    
    D:\002php\shpinx\bin\indexer.exe  -c D:\002php\shpinx\sphinx.conf --merge  goods  goods_new --merge-dst-range is_updated  00  --rotate

    由于sphinx的脚本文件的执行是在内存中执行,又在磁盘中执行的,所以,这个执行的结果需要根据实际生产环境中服务器的运行情况,等待一定时间才能见效,并不会执行了代码就立即生效,因为后台可能在做这个脚本的执行中的数据上的传输与存储。

    展开全文
  • Sphinx

    2012-11-14 10:51:13
    Sphinx 是用来生成文档的,设计的初衷是为了生成python的文档。可以生成html、htmlhelp/chm、qthelp、devhelp、latex、man 等格式的文档。 安装 easy_install -U Sphinx使用 类似于: qdoc3 工作时需要...

    Sphinx 是用来生成文档的,设计的初衷是为了生成python的文档。可以生成html、htmlhelp/chm、qthelp、devhelp、latex、man 等格式的文档。

    安装

    easy_install -U Sphinx使用

    类似于:

    • qdoc3 工作时需要一个 xxx.qdocconf 文件
    • doxygen 工作时需要一个 Doxyfile 文件

    sphinx 工作时需要一个 conf.py 文件

    运行 sphinx:

    sphinx-build -b html sourcedir builddir

    其中,-b 选项控制生成何种格式的文档

    sphinx-quickstart

    sphinx 提供有一个脚本 sphinx-quickstart,该脚本在两个方面可以简化sphinx的使用

    • 该脚本可以生成 conf.py 配置文件,而不必从空白文件创建。
    • 该脚本可以生成一个 Makefile 和 make.bat 文件。这样可以直接运行

    make html

    而不用我们直接来调用

    sphinx-build -b html sourcedir builddir例子

    这是 sphinx-quickstart 默认生成的 index.rst 文件:

    .. Hello Sphinx documentation master file, created by
       sphinx-quickstart on Sat Oct 09 21:32:40 2010.
       You can adapt this file completely to your liking, but it should at least
       contain the root `toctree` directive.

    Welcome to Hello Sphinx's documentation!
    ========================================

    Contents:

    .. toctree::
       :maxdepth: 2

    Indices and tables
    ==================

    * :ref:`genindex`
    * :ref:`search`
    • 一开始 ..  开头的是注释

    • .. toctree:: 是标示符(directive),后可跟参数、选项及内容。

    • 以 ===== 标出的是章节的标题

    • 以 * 开始的是列表

    • :ref: 后面是交叉引用

    • 此处反引号括住的 `genindex` 属于特殊名字(Special names),不可创建该名字的文档

    .. toctree::

    .. toctree::
       :maxdepth: 2
       
       intro
       All about strings <strings>

    包含 toctree 的称为主控文档(master document),除此之外,我们还有一系列的文档,比如intro.rst,strings.rst等,通过此处的 intro 等建立连接。

    展开全文

空空如也

1 2 3 4 5 ... 20
收藏数 9,932
精华内容 3,972
关键字:

sphinx