Copyright © 2006-2010 (coreseek)nzinfo, <li.monan(at)gmail.com>
, (coreseek)HonestQiao, <honestqiao(at)gmail.com>
,
(sphinx)Andrew Aksyonoff, <shodan(at)shodan.ru>
Table of Contents
sphinx.conf
选项参考indexer
程序配置选项searchd
程序配置选项Coreseek
特殊选项参考Sphinx是一个在GPLv2下分发的全文检索引擎;Coreseek 是一个可供企业使用的、基于Sphinx(可独立于Sphinx原始版本运行)的中文全文检索引擎,按照GPLv2协议发行,商业使用(例如, 嵌入到其他程序中)需要联系我们以获得商业授权。
一般而言,Sphinx是一个独立的全文搜索引擎;而Coreseek是一个支持中文的全文搜索引擎,意图为其他应用提供高速、低空间占用、高结果相关度的中文全文搜索能力。Sphinx/Coreseek可以非常容易的与SQL数据库和脚本语言集成。
当前系统内置MySQL和PostgreSQL 数据库数据源的支持,也支持从管道标准输入读取入特定格式的XML数据。通过修改源代码,用户可以自行增加新的数据源(例如:其他类型的DBMS的原生支 持)。在最新的版本中,用户还可以使用Python脚本作为数据源来获取任何已知世界和未知世界的数据,这极大的扩展了数据源的来源。
搜索API支持PHP、Python、Perl、Rudy和Java,并且也可以用作MySQL存储引擎。搜索API非常简单,可以在若干个小时之内移植到新的语言上。
Sphinx 是SQL Phrase Index的缩写,但不幸的和CMU的Sphinx项目重名。
Coreseek (http://www.coreseek.cn/) 为Sphinx在中国地区的用户提供支持服务,如果您不希望纠缠与琐碎的技术细节,请直接联系我们。
本参考手册基于Sphinx 0.9.9最新文档,可能存在潜在的翻译错误,如果您发现本文的翻译错误,请联系我们。
我们的联系方式: coreseek@gmail.com 李沫南(nzinfo) honestqiao@gmail.com 乔楚(HonestQiao 13581882013)
Sphinx原始版本可以从Sphinx官方网站 http://www.sphinxsearch.com/,Coreseek可以从Coreseek官方网站 http://www.coreseek.cn/下载.
目前,Sphinx/Coreseek的发布包包括如下软件:
indexer
: 用于创建全文索引;search
: 一个简单的命令行(CLI) 的测试程序,用于测试全文索引;searchd
: 一个守护进程,其他软件可以通过这个守护进程进行全文检索;sphinxapi
: 一系列searchd 的客户端API 库,用于流行的Web脚本开发语言(PHP, Python, Perl, Ruby, Java).spelldump
: 一个简单的命令行工具,用于从 ispell
或 MySpell
(OpenOffice内置绑定) 格式的字典中提取词条。当使用 wordforms 时可用这些词条对索引进行定制.indextool
: 工具程序,用来转储关于索引的多项调试信息。 此工具是从版本Coreseek 3.1(Sphinx 0.9.9-rc2)开始加入的。mmseg
: 工具程序和库,Coreseek用于提供中文分词和词典处理。This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See COPYING file for details.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
If you don't want to be bound by GNU GPL terms (for instance, if you would like to embed Sphinx in your software, but would not like to disclose its source code), please contact the author to obtain a commercial license.
Coreseek 主要开发人员:
<li.monan(at)gmail.com>
, HonestQiao, <honestqiao(at)gmail.com>
Sphinx 的最初作者和目前的主要开发人员:
<shodan(at)shodan.ru>
为Sphinx的开发出过力的人员和他们的贡献如下(以下排名不分先后):
此外,还有许多人提出了宝贵的想法、错误报告以及修正。在此一并致谢!对Sphinx/Coreseek所采用依赖和工具软件的作者,在此也表示由衷的感谢与敬意。
Coreseek 的开发工作类似Sphinx(起始于2001年),可以上溯到2006年,当时我们试图为一个数据库驱动的网站寻找一个可接受的中文搜索的解决方案,但是当时没有任何方案能够完全而又直接的满足要求。事实上,主要是如下问题:
通过网络,我们了解到有无数的人存在类似的需求,尔后我们进行了不同途径的探索,尝试了不同的走法,经过了反复的实践,最终选择基于Sphinx、结合MMSeg,开发出Coreseek中文全文检索引擎,并按照GPLv2协议发行,以供企业和个人解决中文搜索问题。
年复一年,其他的解决方案有了很多改进,新的方案也不断涌现,但是,我们一致认为仍然没有一种解决方案足够的好,能让我们抛弃Sphinx将搜索平台迁移过去。
近年来,Sphinx/Coreseek的用户给了我们很多正面的反馈和建议,我们也不断改进和提高,并增加了Python数据源,将Sphinx /Coreseek的应用范围从已知世界扩展到未知世界,其应用场景也达到无限种可能;因此,显而易见的,Sphinx/Coreseek的开发过程将会 继续(也许将持续到世界末日)。
在绝大多数现代的Unix类操作系统(例如Linux、BSD等)上,只需要一个C++编译器就可以编译并运行Sphinx/Coreseek,而不需要对源码进行任何改动。
目前,Sphinx/Coreseek可以在以下系统上运行:
支持的CPU种类包括 X86, X86-64, AMD64, SPARC64。目前经过实际测试可以在主流BSD平台、Linux平台和Windows平台运行,详情可以查看Coreseek测试运行环境列表。
我们希望Sphinx/Coreseek也能够在其他的类Unix操作系统平台上工作,为所有需要解决中文搜索问题的用户服务,如果你运行Sphinx/Coreseek索使用的操作系统不在上面的名单中,请告诉我们(HonestQiao, <honestqiao(at)gmail.com>
)。
目前的阶段,Sphinx/Coreseek的Windows版可用于测试、调试和普通生产环境,但不建议用于负载量较大的生产系统。限于 Windows操作系统自身的限制,最突出的两个问题是:1)并发查询的支持不好;2)缺少索引数据热切换的支持。虽然目前已经有用户成功的在生产环境克 服了这两个问题,但是我们仍然不推荐在Windows下运行Sphinx/Coreseek提供高强度的搜索服务。我们推荐使用Linux或者BSD作为 运行的操作系统平台,并可提供Linux、BSD系统下针对性的系统架构和性能优化支持服务。
在类UNIX操作系统平台上,你需要以下的工具用来编译和安装Sphinx/Coreseek:
在Windows平台上,你需要Microsoft Visual C/C++ Studio .NET 2003 or 2005。如果你还需要使用Python数据源,推荐安装ActiveState Python2.6。其他的编译器/开发环境也许也能搞定这件事,但你可能需要自己手工制作他们所需的Makefile或者工程文件。
将你下载的tar包解压,并进入coreseek
子目录:
$ tar xzvf coreseek-3.2.14.tar.gz
$ cd coreseek
首先安装MMSeg:
$ cd mmseg
$ ./configure --prefix=/usr/local/mmseg
$ make
$ make install
$ cd ..
运行配置 程序:
$ ./configure
configure程序有很多运行选项。完整的列表可以通过使用 --help
开关得到。最重要的如下:
--prefix
, 定义将Coreseek安装到何处;比如 --prefix=/usr/local/coreseek
(以下全部示例都假定Coreseek安装在这个位置)--with-mysql
, 当自动检测失败时,指出在那里能找到MySQL 头文件和库文件;--with-pgsql
, 指出在那里能找到PostgreSQL头文件和库文件.--with-mmseg
, 启用基于MMSeg的中文分词法,并指出在那里能找到MMSeg头文件和库文件.--with-python
, 启用Python数据源支持. 需要预先安装Python2.6.编译源代码生成二进制程序:
$ make
安装二进制程序到你设定的目录下: (类Unix操作系统下默认为 /usr/local/bin/
, 但是可以被 configure --prefix
) 修改安装目录
$ make install
在Windows上安装通常比在Linux环境下容易一些。要不是为了给代码制作patch,一般安装预先编译好的二进制文件即可,它们可以在网站的下载区找到.
将你下载的.zip文件解压,比如 coreseek-3.2.14-win32.zip
(或者 coreseek-3.2.13-win32-pgsql.zip
如果你需要PostgresSQL支持.) Windows XP及其后续版本都可以直接解压.zip压缩包,用免费的解压缩程序也可,比如 7Zip.
在本教程的其余部分,我们假定上述压缩包被解压到 C:\usr\local\coreseek
, 这样 searchd.exe
对应的路径就是 C:\usr\local\coreseek\bin\searchd.exe
. 如果你打算给安装目录或者配置文件用个不同的路径,请在相应的地方自行修改路径。
把 searchd
服务安装成一个Windows服务:
C:\usr\local\coreseek>
C:\usr\local\coreseek\bin\searchd.exe --install --config
C:\usr\local\coreseek\etc\coreseek.conf --servicename Coreseek
这样 searchd
服务应该出现在“控制面板->系统管理->服务”的列表中了. 服务应该出现在“控制面板->系统管理->服务”的列表中了,但还没有被启动,因为在启动它之前,我们还需要做些配置并用indexer
建立索引 . 这些可以参考 快速入门教程.
如果 configure
程序没有找到MySQL 的头文件和库文件, 请试试检查是否安装了 mysql-devel
或者 mysql-client
依赖包. 在有些系统上,默认安装包括这个包. 类似如此,libiconv等也可能会有类似的提示。
如果 make
程序给出如下错误提示
/bin/sh: g++: command not found make[1]: *** [libsphinx_a-sphinx.o] Error 127
请检查是否安装了 gcc-c++
包.
如果你在编译时得到如下错误
sphinx.cpp:67: error: invalid application of `sizeof' to incomplete type `Private::SizeError<false>'
这意味着某些编译时的类型检查失败了,一个最有可能的原因是在你的系统上类型off_t的长度小于64bit。一个快速的修复手段是,你可以修改 src/sphinx.h ,将在定义类型SphOffset_t 处,将off_t 替换成DWORD,需要注意,这种改动将使你的全文索引文件不能超过2GB。即便这种修改有用,也请汇报这一问题,在汇报中请包括具体的错误信息以及操作 系统编译器的配置情况。这样,我们可能能够在下一个版本中解决这一问题。
如何你遇到了其他的任何问题,或者前面的建议对你没有帮助,别犹豫,请立刻联系我们.
以下所有的例子都假设你将Sphinx/Coreseek安装在目录 /usr/local/coreseek
, 并且 searchd
对应的路径为 /usr/local/coreseek/bin/searchd
.
为了使用Sphinx/Coreseek,你需要:
创建配置文件.
缺省的配置文件名为 csft.conf
. 全部的Sphinx/Coreseek提供的程序默认都在当前工作的目录下寻找该文件.
由configure
程序生成的示例配置文件sphinx.conf.dist
中包括全部选项的注释,复制并编辑这个文件使之适用于你的具体情况: (请确认 Sphinx/Coreseek 安装在 /usr/local/coreseek/
)
$ cd /usr/local/coreseek/etc
$ cp sphinx.conf.dist csft.conf
$ vi csft.conf
在示例配置文件中,将试图对MySQL数据库test
中的 documents
表建立索引;因此在这里还提供了 example.sql
用于给测试表增加少量数据用于测试:
$ mysql -u test < /usr/local/coreseek/etc/example.sql
运行indexer
为你的数据创建全文索引:
$ cd /usr/local/coreseek/etc
$ /usr/local/coreseek/bin/indexer --all
检索你新创建的索引!
你可以使用search
(注意,是search
而不是searchd
)实用程序从命令行对索引进行检索:
$ cd /usr/local/coreseek/etc
$ /usr/local/coreseek/bin/search test
如果要从PHP脚本检索索引,你需要:
运行守护进程searchd,PHP脚本需要连接到searchd上进行检索:
$ cd /usr/local/coreseek/etc
$ /usr/local/coreseek/bin/searchd
运行PHP API 附带的test 脚本(运行之前请确认searchd守护进程已启动):
$ cd /源代码目录/coreseek/api
$ php test.php test
将API文件(位于api/sphinxapi.php
) 包含进你自己的脚本,开始编程.
祝你搜索愉快!
索引的数据可以来自各种各样不同的来源:SQL数据库、纯文本、HTML文件、邮件等等。从Sphinx/Coreseek的视角看,索引数据是一个结构化的文档的集合,其中每个文档是字段的集合,这和SQL数据库的视角有所不同,在那里,每一行代表一个文档,每一列代表一个字段。
由于数据来源的不同,需要不同的代码来获取数据、处理数据以供Sphinx/Coreseek进行索引的建立。这种代码被称之为数据源驱动程序(简称:驱动或数据源)。
在本文撰写时,Sphinx/Coreseek中包括MySQL和PostgreSQL数据源的驱动程序,这些驱动使用数据库系统提供的C/C++
原生接口连接到数据库服务器并获取数据。此外,Sphinx/Coreseek还提供了额外的被称为xmlpipe的数据源驱动,该驱动运行某个具体的命
令,并从该命令的stdout
中读入数据。数据的格式在 Section 3.8,
“xmlpipe 数据源” 中有介绍。经过发展,Coreseek还提供了具有特色的Python数据源驱动,可以使用Python编写数据获取脚本自定义数据源,从而得以获取任何已知世界和未知世界的数据。
如果确有必要,一个索引的数据可以来自多个数据源。这些数据将严格按照配置文件中定义的顺序进行处理。所有从这些数据源获取到的文档将被合并,共同产生一个索引,如同他们来源于同一个数据源一样。
属性是附加在每个文档上的额外的信息(值),可以在搜索的时候用于过滤和排序。
搜索结果通常不仅仅是进行文档的匹配和相关度的排序,经常还需要根据其他与文档相关联的值,对结果进行额外的处理。例如,用户可能需要对新闻检索结 果依次按日期和相关度排序,检索特定价格范围内的产品,检索某些特定用户的blog日志,或者将检索结果按月分组。为了高效地完成上述工作,Sphinx 允许给文档附加一些额外的属性,并把这些值存储在全文索引中,以便在对全文匹配结果进行过滤、排序或分组时使用。
属性与字段不同,不会被全文索引。他们仅仅是被存储在索引中,属性进行全文检索式不可能的。如果要对属性进行全文检索,系统将会返回一个错误。
例如,如果column被设置为属性,就不能使用扩展表达式@column 1
去匹配column为1的文档;如果数字字段按照普通的方式被索引,那么就可以这样来匹配。
属性可用于过滤,或者限制返回的数据,以及排序或者 结果分组; 也有可能是完全基于属性排序的结果, 而没有任何搜索相关功能的参与. 此外, 属性直接从搜索服务程序返回信息, 而被索引的文本内容则没有返回.
论坛帖子表是一个很好的例子。假设只有帖子的标题和内容这两个字段需要全文检索,但是有时检索结果需要被限制在某个特定的作者的帖子或者属于某个子 论坛的帖子中(也就是说,只检索在SQL表的author_id和forum_id这两个列上有特定值的那些行),或者需要按post_date列对匹配 的结果排序,或者根据post_date列对帖子按月份分组,并对每组中的帖子计数。
为实现这些功能,可以将上述各列(除了标题和内容列)作为属性做索引,之后即可使用API调用来设置过滤、排序和分组。以下是一个例子:
... sql_query = SELECT id, title, content, \ author_id, forum_id, post_date FROM my_forum_posts sql_attr_uint = author_id sql_attr_uint = forum_id sql_attr_timestamp = post_date ...
// only search posts by author whose ID is 123 $cl->SetFilter ( "author_id", array ( 123 ) ); // only search posts in sub-forums 1, 3 and 7 $cl->SetFilter ( "forum_id", array ( 1,3,7 ) ); // sort found posts by posting date in descending order $cl->SetSortMode ( SPH_SORT_ATTR_DESC, "post_date" );
可以通过名字来指示特定的属性,并且这个名字是大小写无关的(注意:直到目前为止,Sphinx还不支持中文作为属性的名称)。属性并不会被全文索引,他们只是按原封不动的存储在索引文件中。目前支持的属性类型如下:
由各个文档的全部的属性信息构成了一个集合,它也被称为文档信息 docinfo. 文档信息可以按如下两种方式之一存储:
.spa
文件中存储), 或者.spd
文件中存储)当采用外部存储方式时,searchd
总是在RAM中保持一份.spa
文件的拷贝(该文件包含所有文档的所有文档信息)。这是主要是为了提高性能,因为磁盘的随机访问太慢了。相反,内联存储并不需要任何额外的RAM,但代价是索引文件的体积大大地增加了;请注意,全部属性值在文档ID出现的每一处都被复制了一份,而文档ID出现的次数恰是文档中不同关键字的数目。仅当有一个很小的属性集、庞大的文本数据集和受限的RAM时,内联存储才是一个可考虑的选择。在大多数情况下,外部存储可令建立索引和检索的效率都大幅提高。
检索时,采用外部存储方式产生的的内存需求为 (1+number_of_attrs)*number_of_docs*4字节,也就是说,带有两个属性和一个时间戳的1千万篇文档会消耗(1+2+1)*10M*4 = 160 MB的RAM。这是每个检索的守护进程(PER DAEMON)消耗的量,而不是每次查询,searchd
仅在启动时分配160MB的内存,读入数据并在不同的查询之间保持这些数据。子进程并不会对这些数据做额外的拷贝。
多值属性MVA (multi-valued attributes)是文档属性的一种重要的特例,MVA使得向文档附加一系列的值作为属性的想法成为可能。这对文章的tags,产品类别等等非常有用。MVA属性支持过滤和分组(但不支持分组排序)。
目前MVA列表项的值被限制为32位无符号整数。列表的长度不受限制,只要有足够的RAM,任意个数的值都可以被附加到文档上(包含MVA值的.spm
文件会被searchd
预缓冲到RAM中)。MVA的源数据来源既可以是一个单独的查询,也可以是文档属性,参考 sql_attr_multi中的来源类型。在第一种情况中,该查询须返回文档ID和MVA值的序对;而在第二种情况中,该字段被分析为整型值。对于多值属性的输入数据的顺序没有任何限制,在索引过程中这些值会自动按文档ID分组(而相同文档ID下的数据也会排序)。
在过滤过程中,MVA属性中的任何一个值满足过滤条件,则文档与 过滤条件匹配(因此通过排他性过滤的文档不会包含任何被禁止的值)。按MVA属性分组时,一篇文档会被分到与多个不同MVA值对应的多个组。例如,如果文 档集只包含一篇文档,它有一个叫做tag的MVA属性,该属性的值是5、7和11,那么按tag的分组操作会产生三个组,它们的@count都是 1,@groupby键值分别是5、7和11。还要注意,按MVA分组可能会导致结果集中有重复的文档:因为每篇文文档可能属于不同的组,而且它可能在多 个组中被选为最佳结果,这会导致重复的ID。由于历史原因,PHP API对结果集的行进行按文档ID的有序hash,因此用PHP API进行对MVA属性的分组操作时你还需要使用 SetArrayResult().
为了快速地相应响应查询,Sphinx需要从文本数据中建立一种为查询做优化的特殊的数据结构。这种数据结构被称为索引(index);而建立索引的过程也叫做索引或建立索引(indexing)。
不同的索引类型是为不同的任务设计的。比如,基于磁盘的B-Tree存储结构的索引可以更新起来比较简单(容易向已有的索引插入新的文档),但是搜起来就相当慢。因此Sphinx的程序架构允许轻松实现多种不同的索引类型。
目前在Sphinx中实现的唯一一种索引类型是为最优化建立索引和检索的速度而设计的。随之而来的代价是更新索引相当的很慢。理论上讲,更新这种索引甚至可能比从头重建索引还要慢。不过大多数情况下这可以靠建立多个索引来解决索引更新慢的问题,细节请参考 Section 3.11, “实时索引更新”.
实现更多的索引类型支持,已列入计划,其中包括一种可以实时更新的类型。
每个配置文件都可以按需配置足够多的索引。indexer
工具可以将它们同时重新索引(如果使用了--all
选项)或者仅更新明确指出的一个。 searchd
工具会为所有被指明的索引提供检索服务,而客户端可以在运行时指定使用那些索引进行检索。
Sphinx/Coreseek索引的源数据有一些限制,其中最重要的一条是:
所有文档的ID必须是唯一的无符号非零整数(根据Sphinx构造时的选项,可能是32位或64位)
如果不满足这个要求,各种糟糕的情况都可能发生。例如,Sphinx/Coreseek建立索引时可能在突然崩溃,或者由于冲突的文档ID而在索引结果中产生奇怪的结果。也可能,一只重达1000磅的大猩猩最后跳出你的电脑,向你扔臭蛋。我告诉过你咯!
当建立索引时,Sphinx从指定的数据源获得文本文档,将文本分成词的集合,再对每个词做大小写转换,于是“Abc”,“ABC”和“abc”都被当作同一个词(word,或者更学究一点,词项term)
为了正确完成上述工作,Sphinx需要知道:
这些都可以用 charset_type
和 charset_table
选项为每个索引单独配置. charset_type
指定文档的编码是单字节的(SBCS)还是UTF-8的。在Coreseek中,如果通过charset_dictpath设置中文词典启动了中文分词模
式后,则可以使用GBK及BIG5的编码;但是在内部实现中,任然是预先转换成UTF-8编码在进行处理的. charset_table
则指定了字母类字符到它们的大小写转换版本的对应表,没有在这张表中出现的字符被认为是非字母类字符,并且在建立索引和检索时被当作词的分割符来看待。
注意,尽管默认的转换表并不包含空格符 (ASCII code 0x20, Unicode U+0020) , 但是这么做是 完全合法的. 这在某些情况下可能有用,比如在对tag云构造索引的时候,这样一个用空格分开的词集就可以被当作一个单独的查询项了.
默认转换表目前包括英文和俄文字符。请您提交您为其他语言撰写的转换表!
在Coreseek中,启用中文分词后,系统会使用MMSeg内置的码表(被硬编码在MMSeg的程序中),因此,charset_table在启用分词后将失效。
对于所有的基于SQL驱动,建立索引的过程如下:
大多数参数是很直观的,例如数据库的用户名、主机、密码。不过,还有一些细节上的问题需要讨论。
索引系统需要通过主查询来获取全部的文档信息,一种简单的实现是将整个表的数据读入内存,但是这可能导致整个表被锁定并使得其他操作被阻止(例如: 在MyISAM格式上的INSERT操作),同时,将浪费大量内存用于存储查询结果,诸如此类的问题吧。 为了避免出现这种情况,Sphinx/Coreseek支持一种被称为 区段查询的技术. 首先,Sphinx/Coreseek从数据库中取出文档ID的最小值和最大值,将由最大值和最小值定义自然数区间分成若干份,一次获取数据,建立索引。现举例如下:
Example 1. 区段查询示例:
# in sphinx.conf sql_query_range = SELECT MIN(id),MAX(id) FROM documents sql_range_step = 1000 sql_query = SELECT * FROM documents WHERE id>=$start AND id<=$end
如果这个表(documents)中,字段ID的最小值和最大值分别是1 和2345,则sql_query将执行3次:
$start
替换为1,并且将 $end
替换为 1000;$start
替换为1001,并且将 $end
替换为 2000;$start
替换为2001,并且将 $end
替换为 2345.显然,这对于只有2000行的表,分区查询与整个读入没有太大区别,但是当表的规模扩大到千万级(特别是对于MyISAM格式的表),分区区段查询将提供一些帮助。
后查询(sql_post)
vs. 索引后查询(sql_post_index)
后查询和索引后查询的区别在于,当Sphinx获取到全部文档数据后,立即执行后查询,但是构建索引的过程仍然may因为某种原因失败。在另一方面,当索引后查询被执行时,可以理所当然的认为索引已经成功构造完了。因为构造索引可能是个漫长的过程,因此对与数据库的连接在执行后索引操作后被关闭,在执行索引后操作前被再次打开。
xmlpipe 数据源是处于让用户能够将现有数据嵌入Sphinx而无需开发新的数据源驱动的目的被设计和提供的。它将每篇文档限制为只能包括两个可全文索引的字段,以及只能包括两个属性。xmlpipe数据源已经被废弃,在Section 3.9, “xmlpipe2 数据源”中描述了xmlpipe的替代品xmlpipe2数据源。对于新的数据,建议采用xmlpipe2。
为了使用xmlpipe,需要将配置文件改为类似如下的样子:
source example_xmlpipe_source { type = xmlpipe xmlpipe_command = perl /www/mysite.com/bin/sphinxpipe.pl }
indexer
实用程序将要运行 xmlpipe_command
, 所指定的命令,而后读取其向标准输出stdout
上输出的数据,并对之进行解析并建立索引。
严格的说,是索引系统打开了一个与指定命令相连的管道,并从这个管道读取数据。
indexer 实用程序假定在从标准输入读入的XML格式的数据中中存在一个或更多的文档。下面是一个包括两个文档的文档数据流的例子:
Example 2. XMLpipe 文档数据流
<document> <id>123</id> <group>45</group> <timestamp>1132223498</timestamp> <title>test title</title> <body> this is my document body </body> </document> <document> <id>124</id> <group>46</group> <timestamp>1132223498</timestamp> <title>another test</title> <body> this is another document </body> </document>
遗留的xmlpipe数据驱动使用内置的解析器来解析xml文档,这个解析器的速度非常快,但是并没有提供对XML格式完整支持。这个解析器需要文档中必须包括全部的字段,并且严格按照例子中给出的格式给出,而且字段的出现顺序需要严格按照例子中给出的顺序。仅有一个字段timestamp
是可选的,它的缺省值为1。
xmlpipe2使你可以用另一种自定义的XML格式向Sphinx传输任意文本数据和属性数据。数据模式(即数据字段的集合或者属性集)可以由XML流本身指定,也可以在配置文件中数据源的配置部分中指定。
在对xmlpipe2数据源做索引时,索引器运行指定的命令,打开一个连接到前述命令标准输出的管道,并等待接受具有正确格式的XML数据流。以下是一个数据流的样本:
Example 3. xmlpipe2 文档流
<?xml version="1.0" encoding="utf-8"?> <sphinx:docset> <sphinx:schema> <sphinx:field name="subject"/> <sphinx:field name="content"/> <sphinx:attr name="published" type="timestamp"/> <sphinx:attr name="author_id" type="int" bits="16" default="1"/> </sphinx:schema> <sphinx:document id="1234"> <content>this is the main content <![CDATA[[and this <cdata> entry must be handled properly by xml parser lib]]></content> <published>1012325463</published> <subject>note how field/attr tags can be in <b class="red">randomized</b> order</subject> <misc>some undeclared element</misc> </sphinx:document> <!-- ... more documents here ... --> </sphinx:docset>
任意多的数据字段和属性都是允许的。数据字段和属性在同一文档元素中出现的先后顺序没有特别要求。。单一字段数据的最大长度有限制,超过2MB的数据会被截短到2MB(但这个限制可以在配置文件中数据源部分中修改)。
XML数据模式(Schema),即数据字段和属性的完整列表,必须在任何文档被分析之前就确定。这既可以在配置文件中用xmlpipe_field
和xmlpipe_attr_XXX
选
项指定,也可以就在数据流中用<sphinx:schema>元素指定。
<sphinx:schema>元素是可选的,但如果出现,就必须是<sphinx:docset>元素的第一个子元素。如果没
有在数据流中内嵌的数据模式定义,配置文件中的相关设置就会生效,否则数据流内嵌的设置被优先采用。
未知类型的标签(既不是数据字段,也不是属性的标签)会被忽略,但会给出警告。在上面的例子中,<misc>标签会被忽略。所有嵌入在其他标签中的标签及其属性都会被无视(例如上述例子中嵌入在<subject>标签中的<b>标签)
支持输入数据流的何种字符编码取决于系统中是否安装了iconv
. xmlpipe2是用 libexpat
解析器解析的,该解析器内置对 US-ASCII, UTF-8, UTF-8 和一些 UTF-16 变体的支持. Sphinx/Coreseek的configure
脚本也会检查 libiconv
是否存在并使用它来处理其他的字符编码。 libexpat
也隐含的要求在Sphinx/Coreseek端使用UTF-8,因为它返回的分析过的数据总是UTF-8的。
xmlpipe2可以识别的XML元素(标签)(以及前述元素可用的属性)如下:
Coreseek支持使用Python编写数据源脚本,从而可以很方便的扩展Sphinx/Coreseek的功能,来轻易的从任何Python可以操作的地方获取需要进行检索的数据。当前,Python几乎支持所有的SQL数据库以及NoSql存储系统,可以查看Python DatabaseInterfaces获得详细列表。
python #用于配置Python数据源程序的PYTHONPATH { path = /usr/local/coreseek/etc/pysource path = /usr/local/coreseek/etc/pysource/csft_demo } source sourcename { type = python #数据类型 name = csft_demo.MainSource #调用的python的类名称 }
在以上配置中,对应的Python数据源脚本,为/usr/local/coreseek/etc/pysource/csft_demo/__init__.py,执行索引操作时,将从该脚本获取数据,请查看Section 10.3, “Python数据源程序接口”了解细节。
有这么一种常见的情况:整个数据集非常大,以至于难于经常性的重建索引,但是每次新增的记录却相当地少。一个典型的例子是:一个论坛有1000000个已经归档的帖子,但每天只有1000个新帖子。
在这种情况下可以用所谓的“主索引+增量索引”(main+delta)模式来实现“近实时”的索引更新。
这种方法的基本思路是设置两个数据源和两个索引,对很少更新或根本不更新的数据建立主索引,而对新增文档建立增量索引。在上述例子中,那 1000000个已经归档的帖子放在主索引中,而每天新增的1000个帖子则放在增量索引中。增量索引更新的频率可以非常快,而文档可以在出现几分种内就 可以被检索到。
确定具体某一文档的分属那个索引的分类工作可以自动完成。一个可选的方案是,建立一个计数表,记录将文档集分成两部分的那个文档ID,而每次重新构建主索引时,这个表都会被更新。
Example 4. 全自动的即时更新
# in MySQL CREATE TABLE sph_counter ( counter_id INTEGER PRIMARY KEY NOT NULL, max_doc_id INTEGER NOT NULL ); # in sphinx.conf source main { # ... sql_query_pre = SET NAMES utf8 sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents sql_query = SELECT id, title, body FROM documents \ WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) } source delta : main { sql_query_pre = SET NAMES utf8 sql_query = SELECT id, title, body FROM documents \ WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) } index main { source = main path = /path/to/main # ... all the other settings } # note how all other settings are copied from main, # but source and path are overridden (they MUST be) index delta : main { source = delta path = /path/to/delta }
请注意,上例中我们显示设置了数据源delta的sql_query_pre
选项,覆盖了全局设置。必须显示地覆盖这个选项,否则对delta做索引的时候也会运行那条REPLACE
查询,那样会导致delta源中选出的数据为空。可是简单地将delta的sql_query_pre
设置成空也不行,因为在继承来的数据源上第一次运行这个指令的时候,继承来的所有值都会被清空,这样编码设置的部分也会丢失。因此需要再次显式调用编码设置查询。
合并两个已有的索引比重新对所有数据做索引更有效率,而且有时候必须这样做(例如在“主索引+增量索引”分区模式中应合并主索引和增量索引,而不是简单地重新索引“主索引对应的数据)。因此indexer
有这个选项。合并索引一般比重新索引快,但在大型索引上仍然不是一蹴而就。基本上,待合并的两个索引都会被读入内存一次,而合并后的内容需要写入磁盘一次。例如,合并100GB和1GB的两个索引将导致202GB的IO操作(但很可能还是比重新索引少)
基本的命令语法如下:
indexer --merge DSTINDEX SRCINDEX [--rotate]
SRCINDEX的内容被合并到DSTINDEX中,因此只有DSTINDEX索引会被改变。 若DSTINDEX已经被searchd
于提供服务,则--rotate
参数是必须的。 最初设计的使用模式是,将小量的更新从SRCINDEX合并到DSTINDEX中。 因此,当属性被合并时,一旦出现了重复的文档ID,SRCINDEX中的属性值更优先(会覆盖DSTINDEX中的值)。 不过要注意,“旧的”关键字在这个过程中并不会被自动删除。
例如,在DSTINDEX中有一个叫做“old”的关键字与文档123相关联,而在SRCINDEX中则有关键字“new”与同一个文档相关,那么在合并后用这两个关键字都能找到文档123。 您可以给出一个显式条件来将文档从DSTINDEX中移除,以便应对这种情况,相关的开关是--merge-dst-range
:
indexer --merge main delta --merge-dst-range deleted 0 0
这个开关允许您在合并过程中对目标索引实施过滤。过滤器可以有多个,只有满足全部过滤条件的文档才会在最终合并后的索引中出现。在上述例子中,过滤器只允许“deleted”为0的那些条件通过,而去除所有标记为已删除(“deleted”)的记录(可以通过调用UpdateAttributes()设置文档的属性)。
有如下可选的匹配模式:
当如下条件满足时,SPH_MATCH_FULLSCAN模式自动代替其他指定的模式被激活:
extern
.在完整扫描模式中,全部已索引的文档都被看作是匹配的。这类匹配仍然会被过滤、排序或分组,但是并不会做任何真正的全文检索。这种模式可以用来统一
全文检索和非全文检索的代码,或者减轻SQL服务器的负担(有些时候Sphinx扫描的速度要优于类似的MySQL查询)。
“在论坛中搜索帖子”这件事可用作完整搜索模式的例子:用SetFilter()
指定用户ID但不提供任何查询词,Sphinx会匹配SetFilter()
所能匹配的全部文档,也就是这个用户ID对应的全部帖子。默认情况下,其结果的第一排序标准是相关度,其次是Sphinx文档ID,正序(较老的文档在前)。
注意,在完整扫描模式中,文档必须有至少一个属性。否则,即便设置docinfo的存储方式为extern,也无法启用完整扫描模式。
布尔查询允许使用下列特殊操作符:
hello & world
hello | world
hello -world hello !world
( hello world )
以下是一个使用了如上全部操作符的例子:
与(AND)操作符为默认操作,所以“hello world”其实就是“hello & world”
或(OR)操作符的优先级高于与操作符,因此“lookingfor cat | dog | mouse”意思是"looking for ( cat | dog | mouse )" 而不是 "(looking for cat) | dog | mouse"
像“-dog”这种查询不能被执行,因为它差不多包括索引所有文档。这既有技术上的原因,也有性能上的原因。从技术上说,Sphinx并不总是保持一个全部文档ID的列表。性能方面,当文档集非常大的时候(即10-100M个文档),对这种执行查询可能需要很长的时间。
在扩展查询模式中可以使用如下特殊操作符:
hello | world
hello -world hello !world
@title hello @body world
@body[50] hello
@(title,body) hello world
@* hello
"hello world"
"hello world"~10
"the world is a wonderful place"/3
aaa << bbb << ccc
raining =cats and =dogs
^hello world$
以下是上述某些操作符的示例:
例子中查询的完整解释如下:
与(AND)操作为默认操作,因此“hello world”意思是“hello”和“world”必须同时存在文档才能匹配。
或(OR)操作符的优先级要高于与操作符,因此"looking for cat | dog | mouse" 意思是"looking for ( cat | dog | mouse )" 而不是"(looking for cat) | dog | mouse";
字段限制(field limit)符(field limit)将其后指定的搜索限制在某个特定的字段中。通常,如果给出的字段名实际并不存在,你会得到一条错误信息。但可以通过在查询的最开始处加上@@relaxed选项来放宽限制。
@@relaxed @nosuchfield my query
当搜索多个具有不同schema的索引时这可能有用
版本Coreseek 3/Sphinx 0.9.9-rc1又引入了字段限位(field position limit)符。它把搜索限制在指定字段(一个或多个)的前N个位置。例如“@body[50] hello”不会匹配那些body字段包含“hello”,但它出现在第51个位置或者更靠后的文档。
近似距离以词为单位,随词数变化而变化,并应用于引号中的全部词。举个例子,"cat dog mouse"~5 这个查询的意思是必须有一个少于8个词的词串,它要包含全部的三个词,也就是说"CAT aaa bbb ccc DOG eee fff MOUSE" 这个文档不会匹配这个查询,因为这个词串正好是8个词。
阀值匹配符引入了一种模糊匹配。它允许至少含有某个阈值数量个匹配词的文档通过。上述例子("the world is a wonderful place"/3)会匹配含有指定的六个词中的至少三个的那些文档。上面例子中的一个查询”the world is a wonderful place”/3匹配的文档至少含有指定的6个词中的3个。
严格有序搜索符(即“在前”搜索符)是在版本0.9.9-rc2中引入的,它的几个参数在被匹配的文档中必须严格按查询中出现的顺序出现。例如,“black << cat”这个查询(不包括引号)可以匹配“black and white cat”,但不能匹配“the cat was black”。顺序操作符的优先级最低,它既可以应用在最简单的关键词上,也可以用在更复杂的表达式上,比如下面也是个正确的查询:
(bag of words) << "exact phrase" << red|green|blue
版本0.9.9-rc1引入了“严格形式”关键字修饰符,它保证关键词在匹配文档中严格以指定的形式出现,而默认行为只要求词根相同。例如,查询“runs”既可以匹配含有“runs”的文档,也可以匹配含有“running”的文档,因为这二者的词根都是“run”——而如果查询是“=runs”,那就只有前者能匹配。严格形式修饰符要求index_exact_words选项处于启用状态。这是个影响关键字的修饰符,可以与其他一些操作符混合使用,例如词组搜索符、近似搜索符和阈值搜索符等。
关键字修饰符“字段开始”和“字段结束”是在版本Coreseek 3.1/Sphinx 0.9.9-rc2中引入的,它们确保只在一个全文字段的最开始或最结束位置匹配关键字。例如,查询“^hello world$”(包括引号,也就是说这个查询是词组搜索符和字段起止修饰符的组合)匹配的文档必然包括某个严格只有“hello world”这个词组的字段。
自版本Coreseek 3/Sphinx 0.9.9-rc1始,可以嵌套任意层数的括号和“非”操作,但这类查询要想能够计算出结果,就必须保证不能隐含地涉及所有文档。
// 正确查询 aaa -(bbb -(ccc ddd)) // 不能计算的查询 -aaa aaa | -bbb
采用何种权值计算函数(目前)取决于查询的模式。
权值计算函数进行如下两部分主要部分:
词组评分根据文档和查询的最长公共子串(LCS,longest common subsequence)的长度进行。因此如果文档对查询词组有一个精确匹配(即文档直接包含该词组),那么它的词组评分就取得了可能的最大值,也就是查询中词的个数。
统计学评分基于经典的BM25函数,该函数仅考虑词频。如果某词在整个数据库中很少见(即文档集上的低频词)或者在某个特定文档中被经常提及(即特定文档上的高频词),那么它就得到一个较高的权重。最终的BM25权值是一个0到1之间的浮点数。
在所有模式中,数据字段的词组评分是LCS乘以用户指定的数据字段权值。数据字段权值是整数,默认为1,且字段的权值必须不小于1。
在SPH_MATCH_BOOLEAN模式中,不做任何权重估计,每一个匹配项的权重都是1。
在SPH_MATCH_ALL和SPH_MATCH_PHRASE模式中,最终的权值是词组评分的加权和。
在SPH_MATCH_ANY模式中,于前面述两模式的基本思想类似,只是每个数据字段的权重都再加上一个匹配词数目。在那之前,带权的词组相关度被额外乘以一个足够大的数,以便确保任何一个有较大词组评分的数据字段都会使整个匹配的相关度较高,即使该数据字段的权重比较低。
在SPH_MATCH_EXTENDED模式中,最终的权值是带权的词组评分和BM25权重的和,再乘以1000并四舍五入到整数。
这个行为将来会被修改,以便使MATCH_ALL和MATCH_ANY这两个模式也能使用BM25算法。这将使词组评分相同的搜索结果片断得到改进,这在只有一个词的查询中尤其有用。
关键的思想(对于除布尔模式以外的全部模式中)是子词组的匹配越好则评分越高,精确匹配(匹配整个词组)评分最高。作者的经验是,这种基于词组相似性的评分方法可以提供比任何单纯的统计模型(比如其他搜索引擎中广泛使用的BM25)明显更高的搜索质量。
可使用如下模式对搜索结果排序:
SPH_SORT_RELEVANCE忽略任何附加的参数,永远按相关度评分排序。所有其余的模式都要求额外的排序子句,子句的语法跟具体的模式有 关。SPH_SORT_ATTR_ASC, SPH_SORT_ATTR_DESC以及SPH_SORT_TIME_SEGMENTS这三个模式仅要求一个属性名。 SPH_SORT_RELEVANCE模式等价于在扩展模式中按"@weight DESC, @id ASC"排序,SPH_SORT_ATTR_ASC 模式等价于"attribute ASC, @weight DESC, @id ASC",而SPH_SORT_ATTR_DESC 等价于"attribute DESC, @weight DESC, @id ASC"。
在SPH_SORT_TIME_SEGMENTS模式中,属性值被分割成“时间段”,然后先按时间段排序,再按相关度排序。
时间段是根据搜索发生时的当前时间戳计算的,因此结果随时间而变化。所说的时间段有如下这些值:
时间段的分法固化在搜索程序中了,但如果需要,也可以比较容易地改变(需要修改源码)。
这种模式是为了方便对Blog日志和新闻提要等的搜索而增加的。使用这个模式时,处于更近时间段的记录会排在前面,但是在同一时间段中的记录又根据相关度排序-这不同于单纯按时间戳排序而不考虑相关度。
在 SPH_SORT_EXTENDED 模式中,您可以指定一个类似SQL的排序表达式,但涉及的属性(包括内部属性)不能超过5个,例如:
@relevance DESC, price ASC, @id DESC
只要做了相关设置,不管是内部属性(引擎动态计算出来的那些属性)还是用户定义的属性就都可以使用。内部属性的名字必须用特殊符号@开头,用户属性按原样使用就行了。在上面的例子里,@relevance
和@id
是内部属性,而price
是用户定义属性。
已知的内置属性:
@rank
和 @relevance
只是 @weight
的别名.
表达式排序模式使您可以对匹配项按任何算术表达式排序,表达式中的项可以是属性值,内部属性(@id和@weight),算术运算符和一些内建的函数。例如:
$cl->SetSortMode ( SPH_SORT_EXPR, "@weight + ( user_karma + ln(pageviews) )*0.1" );
支持的运算符和函数如下。它们是模仿MySQL设计的。函数接受参数,参数的数目根据具体函数的不同而不同。
计算可以以三种不同的精度进行:(a) 单精度32位IEEE754浮点值(默认情况),(b) 32位有符号整数,(c) 64位有符号整数。如果没有任何返回浮点数的操作,表达式分析器会自动切换到整数模式,否则使用默认的浮点模式。比如,对于表达式“a+b”,如果两个参 数都是32位整数的,则它会被以32位整数模式计算,如果两个参数都是整数,而其中一个是64位的,则以64位整数模式计算,否则以浮点模式计算。然而表 达式“a/b”或者“sqrt(a)”却总是使用浮点模式计算,因为这些操作返回非整数的结果,要让前者使用整数模式,可以使用IDIV()。另外,如果 两个参数都是32位的,表达式“a*b”并不会自动提升到64位模式。要想强制64位模式,可以用BIGINT()。(但要注意的是,如果表达式中同时有 浮点数,那么BIGINT()的命运就是简单地被忽略)
比较操作符(比如=和<=)在条件为真时返回1.0,否则返回0.0。例如(a=b)+3
在属性“a”与属性“b”相等时返回4,否则返回3。与MySQL不同,相等性比较符(即=和<>)中引入了一个小的阈值(默认是1e-6)。如果被比较的两个值的差异在阈值之内,则二者被认为相等。
布尔操作符(AND,OR,NOT)是在版本Coreseek 3.1/Sphinx 0.9.9-rc2中引入的,其行为与一般的布尔操作没有两样。它们全部是左结合,而且比之其他操作符,它们有最低的优先级,其中NOT的优先级比AND 和OR高,但仍旧低于所有其他操作符。AND和OR有相同的优先级,因此建议使用括号来避免在复杂的表达式中出现混乱。
全部的一元和二元函数的意义都很明确,他们的行为跟在数学中的定义一样。但IF()
的行为需要点详细的解释。它接受3个参数,检查第一个参数是否为0.0,若非零则返回第二个参数,为零时则返回第三个参数。注意,与比较操作符不同,IF()
并不使用阈值!因此在第一个参数中使用比较结果是安全的,但使用算术运算符则可能产生意料之外的结果。比如,下面两个调用会产生不同的结果,虽然在逻辑上他们是等价的:
IF ( sqrt(3)*sqrt(3)-3<>0, a, b ) IF ( sqrt(3)*sqrt(3)-3, a, b )
在第一种情况下,由于有阈值,比较操作符<>返回0.0(逻辑假),于是IF()
总是返回‘b’。在第二种情况下,IF()
函数亲自擅自在没有阈值的情况下将同样的 sqrt(3)*sqrt(3)-3
与零值做比较。但由于浮点数运算的精度问题,该表达式的结果与0值会有微小的差异,因此该值与零值的相等比较不会通过,上述第二种情况中IF()
会返回‘a’做为结果。
函数BIGINT()于版本Coreseek 3/ Sphinx 0.9.9-rc1引入,它将它的整型参数强行提升到64位,而对浮点参数无效。引入它是为了可以强制某些表达式(如“a*b”)用64位模式计算,即使所有的参数都是32位的。
IDIV() 函数用于两个参数的取整. 其结果为整数, 与 "a/b" 的结果不同.
版本Coreseek 3/ Sphinx 0.9.9-rc1引入了函数IN(expr, val1, val2, …),它需要两个或更多参数,如果第一个参数与后续任何一个参数(val1到valN)相等则返回1,否则返回0。目前,所有被测试是否相等的参数(不包 括expr本身)必须是常量。(支持任意表达式在技术上是可以实现的,未来我们会这么做)。这些常量经过预先排序,测试相等时可以使用二元查找以提高效 率,因此即使参数列表很长IN()也还可以提供较高的速度。自版本0.9.9-rc2始,第一个参数可以是一个MVA多值属性,这种情况下只要MVA中的 任何一个值与后面列表中的任何一个值相等IN()就返回1。
版本0.9.9-rc1引入了函数INTERVAL(expr, point1, point2, point3, …),它接受2个或更多参数,返回第一个小于第一个参数expr的参数的下标:如果expr<point1,返回0;如果 point1<=expr<point2,返回1,一次类推。显然,必须有point1<point2<…<pointN 才能保证这个函数正确工作。
版本0.9.9-rc1引入了函数NOW(),这是个工具函数,将当前时间戳作为32位整数返回。
版本0.9.9-rc2引入函数GEODIST(lat1, long1, lat2, long2),它根据坐标计算两个指定点之间的地表距离。请注意经纬度都要以角度为单位,而结果是以米为单位的。四个参数都可以是任意表达式。当其中一对 参数引用的是文档属性对而另一对参数是常数,系统会自动选择一条优化的路径。
有时将搜索结果分组(或者说“聚类”)并对每组中的结果计数是很有用的-例如画个漂亮的图来展示每个月有多少的blog日志,或者把Web搜索结果按站点分组,或者把找到的论坛帖子按其作者分组。
理论上,这可以分两步实现:首先在Sphinx中做全文检索,再在SQL服务器端对得到的ID分组。但是现实中在大结果集(10K到10M个匹配)上这样做通常会严重影响性能。
为避免上述问题,Sphinx提供了一种“分组模式”,可以用API调用SetGroupBy()来开启。在分组时,根据group-by值给匹配项赋以一个分组。这个值用下列内建函数之一根据特定的属性值计算:
最终的搜索结果中每组包含一个最佳匹配。分组函数值和每组的匹配数目分别以“虚拟”属性 @group 和 @count 的形式返回.
结果集按group-by排序子句排序,语法与SPH_SORT_EXTENDED
排序子句的语法相似。除了@id
和@weight
,分组排序子句还包括:
默认模式是根据groupby函数值降序排列,即按照 "@group desc"
.
排序完成时,结果参数total_found
会包含在整个索引上匹配的组的总数目。
注意: 分组操作在固定的内存中执行,因此它给出的是近似结果;所以total_found
报告的数目可能比实际给出的个分组数目的和多。@count
也可能被低估。要降低不准确性,应提高max_matches
。如果max_matches
允许存储找到的全部分组,那结果就是百分之百准确的。
例如,如果按相关度排序,同时用SPH_GROUPBY_DAY
函数按属性"published"
分组,那么:
从版本0.9.9-rc2开始, 当使用GROUP BY时,可以通过SetSelect() API调用聚合函数 (AVG(), MIN(), MAX(), SUM())
为提高可伸缩性,Sphnix提供了分布式检索能力。分布式检索可以改善查询延迟问题(即缩短查询时间)和提高多服务器、多CPU或多核环境下的吞吐率(即每秒可以完成的查询数)。这对于大量数据(即十亿级的记录数和TB级的文本量)上的搜索应用来说是很关键的。
其关键思想是对数据进行水平分区(HP,Horizontally partition),然后并行处理。
分区不能自动完成,您需要
indexer
和searchd
)的多个实例;searchd
的一些实例上配置一个特殊的分布式索引;这个特殊索引只包括对其他本地或远程索引的引用,因此不能对它执行重新建立索引的操作,相反,如果要对这个特殊索引进行重建,要重建的是那些被这个索引被引用到的索引。
当searchd
收到一个对分布式索引的查询时,它做如下操作
在应用程序看来,普通索引和分布式索引完全没有区别。 也就是说,分布式索引对应用程序而言是完全透明的,实际上也无需知道查询使用的索引是分布式的还是本地的。 (就算是在0.9.9之中, Sphinx也不支持以其他的方式来结合分布式索引进行搜索, 也许在将来会去掉该限制.)
任一个searchd
实例可以同时做为主控端(master,对搜索结果做聚合)和从属端(只做本地搜索)。这有如下几点好处:
如果在单台多CPU或多核机器上使用,一个做为代理对本机进行搜索的searchd实例就可以利用到全部的CPU或者核。
searchd
将全部成功执行的搜索查询都记录在查询日志文件中。以下是一个类似记录文件的例子:
[Fri Jun 29 21:17:58 2007] 0.004 sec [all/0/rel 35254 (0,20)] [lj] test [Fri Jun 29 21:20:34 2007] 0.024 sec [all/0/rel 19886 (0,20) @channel_id] [lj] test
日志格式如下
[query-date] query-time [match-mode/filters-count/sort-mode total-matches (offset,limit) @groupby-attr] [index-name] query
匹配模式(match-mode)可以是如下值之一
排序模式(sort-mode)可以取如下值之一:
此外,如果searchd
启动的时候带参数 --iostats
,那么在列出被搜索的全部索引后还会给出一块数据。.
一个查询日志项看起来就像这样:
[Fri Jun 29 21:17:58 2007] 0.004 sec [all/0/rel 35254 (0,20)] [lj] [ios=6 kb=111.1 ms=0.5] test
多出来的这块数据是关于搜索中执行的I/O操作的信息,包括执行的I/O操作次数、从索引文件中读取数据的kb数和I/O操作占用的时间(尽管这个时间还包括一个后台处理组件所占用的,但主要是I/O时间)
Sphinx的searchd守护程序从 版本0.9.9-rc2开始支持MySQL二进制网络协议,并且能够通过标准的MySQL API访问。例如,“mysql”命令行程序可以很好地工作。以下是用MySQL客户端对Sphinx进行查询的例子:
$ mysql -P 9306 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 0.9.9-dev (r1734) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> SELECT * FROM test1 WHERE MATCH('test') -> ORDER BY group_id ASC OPTION ranker=bm25; +------+--------+----------+------------+ | id | weight | group_id | date_added | +------+--------+----------+------------+ | 4 | 1442 | 2 | 1231721236 | | 2 | 2421 | 123 | 1231721236 | | 1 | 2421 | 456 | 1231721236 | +------+--------+----------+------------+ 3 rows in set (0.00 sec)
请注意mysqld甚至根本没有在测试机上运行。所有事情都是searchd自己搞定的。
新的访问方法是对原生API的一种补充,原生API仍然完美可用。事实上,两种访问方法可以同时使用。另外,原生API仍旧是默认的访问方法。MySQL协议支持需要经过额外的配置才能启用。当然这只需要更动一行配置文件,加入一个协议为mysql41的监听器(listener)就可以了:
listen = localhost:9306:mysql41
如果仅仅支持这个协议但不支持SQL语法,那没什么实际意义。因此Sphinx现在还支持SQL的一个很小的子集,我们给这个子集起个绰号,叫SphinxQL。目前已经实现的语句有:
SELECT 语句,语法仿照标准SQL,但有一些Sphinx特有的扩展,也缺少一些标准SQL的特性(比如(目前)不支持JOIN)。具体地说:
SELECT *, group_id*1000+article_type AS gkey FROM example GROUP BY gkey系统支持将聚集函数(AVG(),MIN(),MAC(),SUM())用在列列表子句中。这些聚集函数的参数既可以是简单的属性也可以是任意表达式。 COUNT(*)被隐含支持,因为使用GROUP BY就会导致@count这列自动被包括在结果集合中。未来可能会添加显式的支持。COUNT(DISTINCT attr)也被支持。目前每个查询中至多只能有一个COUNT(DISTINCT),而且参数必须是属性。这两种限制未来都可能被放宽。
SELECT *, AVG(price) AS avgprice, COUNT(DISTINCT storeid) FROM products WHERE MATCH('ipod') GROUP BY vendorid
SELECT *, INTERVAL(posted,NOW()-7*86400,NOW()-86400) AS timeseg FROM example WHERE MATCH('my search query') GROUP BY siteid WITHIN GROUP ORDER BY @weight DESC ORDER BY timeseg DESC, @weight DESC
SELECT *, @weight*10+docboost AS skey FROM example ORDER BY skey
OPTION <optionname>=<value> [ , ... ]支持设置的选项和允许设置的值如下:
SELECT * FROM test WHERE MATCH('@title hello @body world') OPTION ranker=bm25, max_matches=3000
SHOW WARNINGS 语句,用于获取上一条查询产生的警告信息。返回的信息还包括该查询本身:
mysql> SELECT * FROM test1 WHERE MATCH('@@title hello') \G ERROR 1064 (42000): index test1: syntax error, unexpected TOK_FIELDLIMIT near '@title hello' mysql> SELECT * FROM test1 WHERE MATCH('@title -hello') \G ERROR 1064 (42000): index test1: query is non-computable (single NOT operator) mysql> SELECT * FROM test1 WHERE MATCH('"test doc"/3') \G *************************** 1. row *************************** id: 4 weight: 2500 group_id: 2 date_added: 1231721236 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS \G *************************** 1. row *************************** Level: warning Code: 1000 Message: quorum threshold too high (words=2, thresh=3); replacing quorum operator with AND operator 1 row in set (0.00 sec)
SHOW STATUS 语句,显示一些很有用的性能计数器。仅当searchd
启动时带有--iostats
和--cpustats
开关时,IO和CPU计数器才分别可用。
mysql> SHOW STATUS; +--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | uptime | 216 | | connections | 3 | | maxed_out | 0 | | command_search | 0 | | command_excerpt | 0 | | command_update | 0 | | command_keywords | 0 | | command_persist | 0 | | command_status | 0 | | agent_connect | 0 | | agent_retry | 0 | | queries | 10 | | dist_queries | 0 | | query_wall | 0.075 | | query_cpu | OFF | | dist_wall | 0.000 | | dist_local | 0.000 | | dist_wait | 0.000 | | query_reads | OFF | | query_readkb | OFF | | query_readtime | OFF | | avg_query_wall | 0.007 | | avg_query_cpu | OFF | | avg_dist_wall | 0.000 | | avg_dist_local | 0.000 | | avg_dist_wait | 0.000 | | avg_query_reads | OFF | | avg_query_readkb | OFF | | avg_query_readtime | OFF | +--------------------+-------+ 29 rows in set (0.00 sec)
SHOW META 语句,显示关于上一条查询的一些额外的元信息(meta-information),比如查询时间和关于关键词的统计信息:
mysql> SELECT * FROM test1 WHERE MATCH('test|one|two'); +------+--------+----------+------------+ | id | weight | group_id | date_added | +------+--------+----------+------------+ | 1 | 3563 | 456 | 1231721236 | | 2 | 2563 | 123 | 1231721236 | | 4 | 1480 | 2 | 1231721236 | +------+--------+----------+------------+ 3 rows in set (0.01 sec) mysql> SHOW META; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | total | 3 | | total_found | 3 | | time | 0.005 | | keyword[0] | test | | docs[0] | 3 | | hits[0] | 5 | | keyword[1] | one | | docs[1] | 1 | | hits[1] | 2 | | keyword[2] | two | | docs[2] | 1 | | hits[2] | 2 | +---------------+-------+ 12 rows in set (0.00 sec)
就像其他地方已经提到的,Sphinx不是个名叫“sphinx”的单独可执行程序,而是由四个独立的程序共同组成的。本节介绍这些工具和他们的用法。
indexer
是Sphinx的两个关键工具之一。不管是从命令行直接调用,还是作为一个较大的脚本的一部分使用,indexer
都只负责一件事情——收集要被检索的数据。
indexer
的调用语法基本上是这样:
indexer [OPTIONS] [indexname1 [indexname2 [...]]]
用户可以在sphinx.conf
中设置好可能有哪些索引(index)(这些索引可以在晚些时候别搜索),因此在调用indexer
的时候,最简单的情况下,只需要告诉它你要简历哪个(或者哪些)索引就行了。
假设 sphinx.conf
包含了两个索引的具体设置, mybigindex
和 mysmallindex
, ,你可以这么调用:
$ indexer mybigindex $ indexer mysmallindex mybigindex
在配置文件sphinx.conf
里面,用户可以为他们的数据指定一个或多个索引。然后调用indexer
来对其中一个特定的索引进行重新编制索引操作,或者是重新编制所有索引——不限于某一个或同时全部,用户总是可以指定现有索引的一个组合。
indexer
的大部分选项都可以在配置文件中给出,然而有一部分选项还需要在命令行上指定,这些选项影响编制索引这一操作是如何进行的。这些选项列举如下:
--config <file>
(简写为-c <file>
) 使 indexer
将指定的文件file作为配置文件。 通常,indexer
是会在安装目录(例如e.g. /usr/local/sphinx/etc/sphinx.conf
,如果sphinx被安装在/usr/local/sphinx
)中寻找sphinx.conf
,若找不到,则继续在用户在shell中调用indexer
时所在的目录中寻找。
这个选项一般在共享sphinx安装的情况下使用,比如二进制文件安装在/usr/local/sphinx
,而不同用户都有权定制自己的sphinx设置。或者在同一个服务器上运行多个实例的情况下使用。在上述两中情况中,用户可以创建自己的sphinx.conf
文件,然后把它做为参数传给indexer。例如:
$ indexer --config /home/myuser/sphinx.conf myindex
--all
使indexer
对sphinx.conf
文件中列出的所有索引进行重新编制索引,这样就不比一次列出每个索引的名字了。这个选项在配置文件较小的情况下,或者在类似基于cron
的维护工作中很有用。在上述情况中,整个索引集每天或每周或别的什么合适的时间间隔中就重新建立一次。用法示例:
$ indexer --config /home/myuser/sphinx.conf --all
--rotate
用于轮换索引。对新的文档建立索引时几乎肯定都确保搜索服务仍然可用,除非你有信心在搜索服务停止同时不给你的用户带来困扰。--rotate
建立一个额外的索引,并列于原有索引(与原有索引在相同目录,简单地在原有索引文件名基础上加一个.new
后缀)。一旦这个额外的索引建立完成,indexer
给searchd
发一个SIGHUP信号做为通知。searchd
会尝试将索引重新命名(给原有索引加上.old
后缀,而把带有.new
后缀的新索引改为原名,以达替换之目的),继而用新的文件重启服务。依 seamless_rotate 选项设定之不同,在新索引可用之前可能有一点小的延迟。用法示例:
$ indexer --rotate --all
--quiet
使indexer
不输出除错误(error)外的任何东西。这个选项仍然拽可用在cron
定时任务的情境下或者脚本中,这些情况下大部分输出是无关紧要或完全没用的,除非是发生了某些种类的错误。用法示例:
$ indexer --rotate --all --quiet
--noprogress
不随时显示进度信息,而是仅在索引结束时报告最终的状态细节(例如为哪些文档建立了索引,建立索引的速度等)。当脚本没有运行在一个控制台(console,或“tty”)时,这个选项是默认的。用法示例:
$ indexer --rotate --all --noprogress
--buildstops <outputfile.text> <N>
像建立索引一样扫描索引对应的数据源,产生一个最终会被加入索引的词项的列表。换种说法,产生一个用这个索引可以检索的词项的列表。注意,这个选项使indexer并不真正更新指定的索引,而只是“假装”建在立索引似地处理一遍数据,包括运行sql_query_pre
或者sql_query_post
选项指定的查询。outputfile.txt
文件最终会包含一个词表,每行一个词,按词频排序,高频在前。参数N指定了列表中最多可出现的词项数目,如果N比索引中全部词项的数目还大,则返回的词项数就是全部词项数。客户端应用程序利用这种字典式的词表来提供“您是要搜索。。。吗?(Did
you mean…)”的功能,通常这个选项与下面要讲的--buildfreqs
选项一同使用。示例:
$ indexer myindex --buildstops word_freq.txt 1000这条命令在当前目录产生一个
word_freq.txt
文件,内含myindex这个索引中最常用的1000个词,且最常用的排在最前面。注意,当指定了多个索引名或使用了--all
选项(相当于列出配置文件中的所有索引名)时,这个选项对其中的最后一个索引起作用。--buildfreqs
与 --buildstops
一同使用 (如果没有指定 --buildstops
则--buildfreqs
也被忽略). 它给--buildstops
产生的词表的每项增加一个计数信息,即该词在索引中共出现了多少次,这在建立停用词(stop
words,出现特别普遍的词)表时可能有用。在开发“您是要搜索。。。吗?(Did you mean…)”的功能时这个选项也能帮上忙,因为有了它你就能知道一个词比另一个相近的词出现得更频繁的程度。示例:
$ indexer myindex --buildstops word_freq.txt 1000 --buildfreqs这个命令将产生一个类似于上一条命令的
word_freq.txt
,但不同在于,每个词的后面都会附加一个数字,指明在指定的索引中这个词出现了多少次。--merge <dst-index> <src-index>
用于在物理上将多个索引合并,比方说你在使用“主索引+增量索引”模式,主索引很少改变,但增量索引很频繁地重建,而--merge
选项允许将这两个索引合而为一。操作是从右向左进行的,即先考察src-index
的内容,然后在物理上将之与dst-index
合并,最后结果留在dst-index
里。用伪代码说就是dst-index
+= src-index
。示例:
$ indexer --merge main delta --rotate上例中main是主索引,很少更动,delta是增量索引,频繁更新。上述命令调用
indexer
将delta的内容合并到main里面并且对索引进行轮换。--merge-dst-range <attr> <min> <max>
在合并索引的时候运行范围过滤。具体地说,向目标索引 (是 --merge
的一个参数,如果没有指定 --merge
, 则--merge-dst-range
也被忽略)合并时,indexer
会对将要合并进去的文档做一次过滤,只有通过过滤才能最终出现在目标索引中。举一个实用的例子,假设某个索引有一个“已删除(deleted)”属性,0代表“尚未删除”。这样一个索引可以用如下命令进行合并:
$ indexer --merge main delta --merge-dst-range deleted 0 0这样标记为已删除的文档(值为1)就不会出现在新生成的目标索引中了。这个选项可以在命令行上指定多次,以便指定多个相继的过滤,这样一个文档要想合并到最终的目标索引中去,就必须依次通过全部这些过滤。
searchd
也是sphinx的两个关键工具之一。 searchd
是系统实际上处理搜索的组件,运行时它表现得就像一种服务,他与客户端应用程序调用的五花八门的API通讯,负责接受查询、处理查询和返回数据集。
不同于 indexer
, searchd
并不是设计用来在命令行或者一般的脚本中调用的,
相反,它或者做为一个守护程序(daemon)被init.d调用(在Unix/Linux类系统上),或者做为一种服务(在Windows类系统上),
因此并不是所有的命令行选项都总是有效,这与构建时的选项有关。
调用 searchd
就像这么简单:
$ searchd [OPTIONS]
不管 searchd
是如何构建的,下列选项总是可用:
--help
(可以简写为 -h
) 列出可以在你当前的 searchd
构建上调用的参数。--config <file>
(可简写为 -c <file>
) 使 searchd
使用指定的配置文件,与上述indexer
的--config
开关相同。--stop
用来停掉 searchd
,使用sphinx.conf
中所指定的PID文件,因此您可能还需要用--config
选项来确认searchd
使用哪个配置文件。值得注意的是,调用 --stop
会确保用 UpdateAttributes()
对索引进行的更动会反应到实际的索引文件中去。示例:
$ searchd --config /home/myuser/sphinx.conf --stop
--status
用来查询运行中的searchd
实例的状态,,使用指定的(也可以不指定,使用默认)配置文件中描述的连接参数。它通过配置好的第一个UNIX套接字或TCP端口与运行中的实例连接。一旦连接成功,它就查询一系列状态和性能计数器的值并把这些数据打印出来。在应用程序中,可以用Status() API调用来访问相同的这些计数器。示例:
$ searchd --status $ searchd --config /home/myuser/sphinx.conf --status
--pidfile
用来显式指定一个PID文件。PID文件存储着关于searchd
的进程信息,这些信息用于进程间通讯(例如indexer
需要知道这个PID以便在轮换索引的时候与searchd
进行通讯)searchd
在正常模式运行时会使用一个PID(即不是使用--console选项启动的),但有可能存在searchd
在控制台(--console
)模式运行,而同时正在索引正在进行更新和轮换操作的情况,此时就需要一个PID文件。
$ searchd --config /home/myuser/sphinx.conf --pidfile /home/myuser/sphinx.pid
--console
用来强制searchd
以控制台模式启动;典型情况下searchd
像一个传统的服务器应用程序那样运行,它把信息输出到(sphinx.conf
配
置文件中指定的)日志文件中。但有些时候需要调试配置文件或者守护程序本身的问题,或者诊断一些很难跟踪的问题,这时强制它把信息直接输出到调用他的控制
台或者命令行上会使调试工作容易些。同时,以控制台模式运行还意味着进程不会fork(因此搜索操作都是串行执行的),也不会写日志文件。(要特别注意,searchd
并不是被主要设计用来在控制台模式运行的)。可以这样调用searchd
:
$ searchd --config /home/myuser/sphinx.conf --console
--iostats
当使用日志时(必须在sphinx.conf
中启用query_log
选项)启用--iostats
会对每条查询输出关于查询过程中发生的输入输出操作的详细信息,会带来轻微的性能代价,并且显然会导致更大的日志文件。更多细节请参考 query
log format 一节。可以这样启动searchd
:
$ searchd --config /home/myuser/sphinx.conf --iostats
--cpustats
使实际CPU时间报告(不光是实际度量时间(wall time))出现在查询日志文件(每条查询输出一次)和状态报告(累加之后)中。这个选项依赖clock_gettime()系统调用,因此可能在某些系统上不可用。可以这样启动searchd
:
$ searchd --config /home/myuser/sphinx.conf --cpustats
--port portnumber
(可简写为 -p
) 指定searchd
监听的端口,通常用于调试。这个选项的默认值是9312,但有时用户需要它运行在其他端口上。在这个命令行选项中指定端口比配置文件中做的任何设置优先级都高。有效的端口范围是0到65535,但要使用低于1024的端口号可能需要权限较高的账户。使用示例:
$ searchd --port 9313
--index <index>
强制searchd
只提供针对指定索引的搜索服务。跟上面的--port
相同,这主要是用于调试,如果是长期使用,则应该写在配置文件中。使用示例:
$ searchd --index myindex
searchd
在Windows平台上有一些特有的选项,与它做为windows服务所产生的额外处理有关,这些选项只存在于Windows二进制版本。
注意,在Windows上searchd默认以--console
模式运行,除非用户将它安装成一个服务。
--install
将searchd
安装成一个微软管理控制台(Microsoft Management Console, 控制面板 / 管理工具 / 服务)中的服务。如果一条命令指定了--install
,那么同时使用的其他所有选项,都会被保存下来,服务安装好后,每次启动都会调用这些命令。例如,调用searchd
时,我们很可能希望用--config
指定要使用的配置文件,那么在使用--install
的同时也要加入这个选项。一旦调用了这个选项,用户就可以在控制面板中的管理控制台中对searchd进行启动、停止等操作,因此一切可以开始、停止和重启服务的方法对searchd
也都有效。示例:
C:\WINDOWS\system32> C:\Sphinx\bin\searchd.exe --install --config C:\Sphinx\sphinx.conf如果每次启动
searchd
你都希望得到I/O stat信息,那就应该把这个选项也用在调用--install
的命令行里:
C:\WINDOWS\system32> C:\Sphinx\bin\searchd.exe --install --config C:\Sphinx\sphinx.conf --iostats
--delete
在微软管理控制台(Microsoft Management Console)和其他服务注册的地方删除searchd,当然之前要已经通过--install
安装过searchd
服务。注意,这个选项既不删除软件本身,也不删除任何索引文件。调用这个选项之后只是使软件提供的服务不能从windows的服务系统中调用,也不能在机器重启后自动启动了。如果调用时searchd
正在做为服务运行中,那么现有的示例并不会被结束(一直会运行到机器重启或调用--stop
)。如果服务安装时(用--servicename
)指定了自定义的名字,那在调用此选项卸载服务时里也需要用--servicename
指定相同的名字。示例:
C:\WINDOWS\system32> C:\Sphinx\bin\searchd.exe --delete
--servicename <name>
在安装或卸载服务时指定服务的名字,这个名字会出现在管理控制台中。有一个默认的名字searchd
,但若安装服务的系统可能有多个管理员登录,或同时运行多个searchd
实例,那么起一个描述性强的名字将是个好好主意。注意,只有在与--install
或者--delete
同时使用的时候--servicename
才有效,否则这个选项什么都不做。示例:
C:\WINDOWS\system32> C:\Sphinx\bin\searchd.exe --install --config C:\Sphinx\sphinx.conf --servicename SphinxSearch
--ntservice
在Windows平台,管理控制台将searchd
做为服务调用时将这个选项传递给它。通常没有必要直接调用这个开关,它是为Windows系统准备的,当服务启动时,系统把这个参数传递给searchd
。然而理论上,你也可以用这个开关从命令行将searchd
启动成普通服务模式(与--console
代表的控制台模式相对)最后但并非最不重要的,类似其他的守护进程(daemon),searchd
多种信号。
search
是Sphinx中的一个辅助工具。searchd
负责服务器类环境中的搜索,而search
专注于在命令行上对索引进行快速测试,而不需要构建一个复杂的架构来处理到服务器端的连接和处理服务器返回的响应。
注意:search
并不是设计用来做为客户端应用程序的一部分。我们强烈建议用户不要针对search
编写接口,相反,应该针对searchd
。Sphinx提供的任何客户端API也都不支持这种用法。(任何时候search
总是每次都重新调入索引,而searchd
会把索引缓冲在内存中以利性能)。
澄清了这些我们就可以继续了。很多通过API构造的查询也可以用search
来做到,然而对于非常复杂的查询,可能还是用个小脚本和对应的API调用来实现比较简单。除此之外,可能有些新的特性先在searchd
系统中实现了而尚未引入到search
中。
search
的调用语法如下:
search [OPTIONS] word1 [word2 [word3 [...]]]
调用search
并不要求searchd
正在运行,只需运行search
的账户对配置文件和索引文件及其所在路径有读权限即可。
默认行为是对在配置文件中设置的全部索引的全部字段搜索word1(AND word2 AND word3….)。如果用API调用来构建这个搜索,那相当于向SetMatchMode
传递参数SPH_MATCH_ALL
,然后在调用Query
的时候指定要查询的索引是*
。
search
有很多选项。首先是通用的选项:
--config <file>
(可简写为 -c <file>
) 使search
使用指定的配置文件,这与上述indexer
的对应选项相同。--index <index>
(可简写为 -i <index>
) 使search
仅搜索指定的索引。通常它会尝试搜索sphinx.conf
中列出的全部物理索引,不包括分布式索引。--stdin
使search
接受标准输入(STDIN)上传入的查询,而不是命令行上给出的查询。有时你要用脚本通过管道给search传入查询,这正是这个选项的用武之地。设置匹配方式的选项:
--any
(可简写为 -a
) 更改匹配模式,匹配指定的任意一个词(word1 OR word2 OR word3),这对应API调用中向SetMatchMode
传递参数SPH_MATCH_ANY
。--phrase
(可简写为 -p
) 更改匹配模式,将指定的全部词做为一个词组(不包括标点符号)构成查询,这对应API调用中向SetMatchMode
传递参数SPH_MATCH_PHRASE
。--boolean
(可简写为-b
) 将匹配模式设为 Boolean matching。注意如果在命令行上使用布尔语法,可能需要对某些符号(用反斜线“\”)加以转义,以避免外壳程序(shell)或命令行处理器对这些符号做特殊理解,例如,在Unix/Linux系统上必须转义“&”以防止search
被fork成一个后台进程,尽管这个问题也可以像下文一样通过使用--stdin
选项来解决。这个选项对应API调用中向SetMatchMode
传递参数SPH_MATCH_BOOLEAN
。--ext
(可简写为 -e
) 将匹配模式设为Extended matching。这对应与API调用中向SetMatchMode
传递参数SPH_MATCH_EXTENDED
。要注意的是因为已经有了更好的扩展匹配模式版本2,所以并不鼓励使用这个选项,见下一条说明。--ext2
(可简写为 -e2
) 将匹配模式设为 Extended matching,
version 2。这个选项对应在API调用中向SetMatchMode
传递参数SPH_MATCH_EXTENDED2
。要注意这个选项相比老的扩展匹配模式更有效也提供更多的特性,因此推荐使用这个新版的选项。--filter <attr> <v>
(可简写为 -f <attr> <v>
) 对结果进行过滤,只有指定的属性attr匹配指定的值v时才能通过过滤。例如--filter deleted 0
只匹配那些有deleted属性,并且其值是0的文档。也可以在命令行上多次给出--filter
以便指定多重过滤,但是如果重复定义针对同一个属性的过滤器,那么第二次指定的过滤条件会覆盖第一次的。用于处理搜索结果的选项:
--limit <count>
(可简写为 -l count
) 限制返回的最多匹配结果数。如果指定了分组(group)选项,则表示的是返回的最多匹配组数。默认值是20个结果(与API相同)--offset <count>
(可简写为 -o <count>
) 从第count个结果开始返回,用于给搜索结果分页。如果想要每页20个结果,那么第二页就从偏移量20开始,第三页从偏移量40开始,以此类推。--group <attr>
(可简写为-g <attr>
) 搜索结果按照指定的属性attr进行分组。类似SQL中的GROUP BY子句,这会将attr属性值一致的结果结合在一起,返回的结果集中的每条都是一组中最好的那条结果。如果没有特别指定,那“最好”指的是相关度最大的。--groupsort <expr>
(可简写为 -gs <expr>
) 尽搜索结果根据-group
分组后,再用表达式<expr>的值决定分组的顺序。注意,这个选项指定的不是各组内部哪条结果是最好的,而是分组本身返回的顺序。--sortby <clause>
(可简写为 -s <clause>
) 指定结果按照<clause>中指定的顺序排序。这使用户可以控制搜索结果展现时的顺序,即根据不同的列排序。例如,--sortby "@weight DESC entrytime DESC"
的意思是将结果首先按权值(相关度)排序,如果有两条或以上结果的相关度相同,则他们的顺序由时间值entrytime决定,时间最近(值最大)的排在前面。通常需要将这些项目放在引号里(--sortby
"@weight DESC"
)或者用逗号隔开(--sortby @weight,DESC
),以避免它们被分开处理。另外,与通常的排序模式相同,如果指定了--group
(分组),这个选项就影响分组内部的结果如何排序。--sortexpr expr
(可简写为 -S expr
) 搜索结果展现的顺序由指定的算术表达式expr决定。例如: --sortexpr "@weight + ( user_karma + ln(pageviews) )*0.1"
(再次提示,要用引号来避免shell对星号*做特殊处理)。扩展排序模式在Sorting
modes 一章下的SPH_SORT_EXTENDED
条目下具体讨论。--sort=date
搜索结果按日期升序(日期较久远的在前)排列。要求索引中有一个属性被指定为时间戳。要求索引中有一个属性被指定为时间戳。--rsort=date
specifies
that the results should be sorted by ascending (i.e. oldest first)
date. This requires that there is an attribute in the index that is set
as a timestamp.--sort=ts
搜索结果按时间戳分成组。先返回时间戳在最近一小时内的这组结果,在组内部按相关度排序。其后返回时间戳为最近一天之内的结果,也按相关度排序。再之后是最近一周的,最后是最近一个月的。在Sorting
modes 一章的SPH_SORT_TIME_SEGMENTS
条目下对此有更详细的讨论。其他选项:
--noinfo
(可简写为-q
) 令search
不在SQL数据库中查询文档信息(Document Info)。具体地说,为了调试search
和MySQL共同使用时出现的问题,你可以在使用这个选项的同时提供一个根据文档ID搜索整个文章全文的查询。细节可参考sql_query_info指令。spelldump
是Sphinx的一个辅助程序。
用于从ispell
或者MySpell
格式的字典文件中可用来辅助建立词形列表(wordforms)的内容——词的全部可能变化都预先构造好。
一般用法如下:
spelldump [options] <dictionary> <affix> [result] [locale-name]
两个主要参数是词典的主文件([language-prefix].dict
)和词缀文件([language-prefix].aff
);通常这两种文件被命名为[语言简写].dict和[语言简写].aff,大多数常见的Linux发行版中都有这些文件,网上也到处找得到。
[result]
指定的是字典数据的输出位置,而[locale-name]
指定了具体使用的区域设置(locale)
还有一个-c [file]
选项,用来指定一个包含大小写转换方面细节的文件。
用法示例:
spelldump en.dict en.aff spelldump ru.dict ru.aff ru.txt ru_RU.CP1251 spelldump ru.dict ru.aff ru.txt .1251
结果文件会包含字典中包含的全部词,字典序排列,wordforms文件格式。可以根据具体的使用环境定制这些文件。结果文件的一个例子:
zone > zone zoned > zoned zoning > zoning
indextool
是版本0.9.9-rc2中引入的辅助工具。用于输出关于物理索引的多种调试信息。(未来还计划加入索引验证等功能,因此起名较indextool而不是indexdump)。 基本用法如下:
indextool <command> [options]
唯一一个所有命令都有的选项是--config
,用于指定配置文件:
--config <file>
(可简写为 -c <file>
) 覆盖默认的配置文件名。其他可用的命令如下:
--dumpheader FILENAME.sph
在设计任何其他索引文件甚至配置文件的前提下,快速输出索引头文件的内容,包括索引的全部设置,尤其是完整的属性列表、字段列表。在版本0.9.9-rc2之前,这个命令是由search工具提供的。--dumpheader INDEXNAME
输出给定索引名的索引头内容,索引头文件的路径是在配置文件中查得的。--dumpdocids INDEXNAME
输出给定索引名涉及的文档ID。数据是从属性文件(.spa)中抽取的,因此要求doc_info=extern正常工作。--dumphitlist INDEXNAME KEYWORD
输出指定关键字KEYWORD在执行索引中的的全部出现。Sphnix有几种不同编程语言的searchd客户端API的实现。在本文完成之时,我们对我们自己的PHP,Python和java实现提供官方支持。此外,也有一些针对Perl,Ruby和C++的第三方免费、开源API实现。
API的参考实现是用PHP写成的,因为(我们相信)较之其他语言,Sphinx在PHP中应用最广泛。因此这份参考文档基于PHP API的参考,而且这节中的所有的代码样例都用PHP给出。
当然,其他所有API都提供相同的方法,也使用完全相同的网络协议。因此这份文档对他们同样适用。在方法命名习惯方面或者具体数据结构的使用上可能会有小的差别。但不同语言的API提供的功能上绝不会有差异。
原型: function GetLastError()
以可读形式返回最近的错误描述信息。如果前一次API调用没有错误,返回空字符串。
任何其他函数(如 Query())失败后(函数失败一般返回false),都应该调用这个函数,它将返回错误的描述。
此函数本身并不重置对错误描述,因此如有必要,可以多次调用。
原型: function GetLastWarning ()
以可读格式返回最近的警告描述信息。如果前一次API调用没有警告,返回空字符串。
您应该调用这个函数来确认您的请求(如 Query())是否虽然完成了但产生了警告。例如,即使几个远程代理超时了,对分布式索引的搜索查询也可能成功完成。这时会产生一个警告信息。
此函数本身不会重置警告信息,因此如有必要,可以多次调用。
原型: function SetServer ( $host, $port )
设置searchd
的主机名和TCP端口。此后的所有请求都使用新的主机和端口设置。默认的主机和端口分别是“localhost”和9312。
原型: function SetRetries ( $count, $delay=0 )
设置分布式搜索重试的次数和延迟时间。
对于暂时的失败,searchd
对每个代理重试至多$count
次。$delay
是两次重试之间延迟的时间,以毫秒为单位。默认情况下,重试是禁止的。注意,这个调用不会使API本身对暂时失败进行重试,它只是让searchd
这样做。目前暂时失败包括connect()调用的各种失败和远程代理超过最大连接数(过于繁忙)的情况。
原型: function SetConnectTimeout ( $timeout )
设置连接超时时间,在与服务器连接时,如果超过这个时间没有连上就放弃。
有时候服务器在响应上会有所延迟,这有可能由于网络的延时,也有可能是因为服务器未处理完的查询太多,堆积所致。不管是什么情况,有了这个选项,就给客户端应用程序提供了一定的控制权,让它可以决定当searchd
不可用的时候如何处理,而且可以避免脚本由于超过运行限制而运行失败(尤其是在PHP里)
当连接失败的而时候,会将合适的错误码返回给应用程序,以便在应用程序级别进行错误处理和通知用户。
原型: function SetArrayResult ( $arrayresult )
PHP专用。控制搜索结果集的返回格式(匹配项按数组返回还是按hash返回)
$arrayresult
参数应为布尔型。如果$arrayresult
为false
(默认),匹配项以PHP hash格式返回,文档ID为键,其他信息(权重、属性)为值。如果$arrayresult
为true
,匹配项以普通数组返回,包括匹配项的全部信息(含文档ID)
这个调用是对MVA属性引入分组支持时同时引入的。对MVA分组的结果可能包含重复的文档ID。因此需要将他们按普通数组返回,因为hash对每个文档ID仅能保存一个记录。
原型: function SetLimits ( $offset, $limit, $max_matches=0, $cutoff=0 )
给服务器端结果集设置一个偏移量($offset
)和从那个偏移量起向客户端返回的匹配项数目限制($limit
)。并且可以在服务器端设定当前查询的结果集大小($max_matches
),另有一个阈值($cutoff
),当找到的匹配项达到这个阀值时就停止搜索。全部这些参数都必须是非负整数。
前两个参数的行为与MySQL LIMIT子句中参数的行为相同。他们令searchd
从编号为$offset
的匹配项开始返回最多$limit
个匹配项。偏移量($offset
)和结果数限制($limit
)的默认值分别是0和20,即返回前20个匹配项。
max_matches
这个设置控制搜索过程中searchd
在内存中所保持的匹配项数目。一般来说,即使设置了max_matches
为1,全部的匹配文档也都会被处理、评分、过滤和排序。但是任一时刻只有最优的N个文档会被存储在内存中,这是为了性能和内存使用方面的原因,这个设置正是控制这个N的大小。注意,max_matches
在两个地方设置。针对单个查询的限制由这个API调用指定。但还有一个针对整个服务器的限制,那是由配置文件中的max_matches
设置控制的。为防止滥用内存,服务器不允许单个查询的限制高于服务器的限制。
在客户端不可能收到超过max_matches
个匹配项。默认的限制是1000,您应该不会遇到需要设置得更高的情况。1000个记录足够向最终用户展示了。如果您是想将结果传输给应用程序以便做进一步排序或过滤,那么请注意,在Sphinx端完成效率要高得多。
$cutoff
设置是为高级性能优化而提供的。它告诉searchd
在找到并处理$cutoff
个匹配后就强制停止。
原型: function SetMaxQueryTime ( $max_query_time )
设置最大搜索时间,以毫秒为单位。参数必须是非负整数。默认值为0,意思是不做限制。
这个设置与SetLimits()中的$cutoff
相似,不过这个设置限制的是查询时间,而不是处理的匹配数目。一旦处理时间已经太久,本地搜索查询会被停止。注意,如果一个搜索查询了多个本地索引,那这个限制独立地作用于这几个索引。
原型: function SetOverride ( $attrname, $attrtype, $values )
设置一个临时的(只对单个查询有效)针对不同文档的属性值覆盖。只支持标量属性。$value是一个哈希表,他的键是要覆盖属性的文档ID,之是对应该文档ID的要覆盖的值。 于版本0.9.9-rc1引入。
属性覆盖特性使用户可以针对一次查询“临时性地”修改一些文档的值,不影响其他查询。这个函数可以用来进行数据个性化。例如,假设正在实现一个个性 化搜索函数,用来将朋友推荐的帖子排在前面,这类数据不仅是动态的,而且是个性化的,因此不能简单地把这种数据放入索引,因为不能影响其他用户的搜索。而 覆盖机制是针对单个查询的,不会影响其他人。因此可以,比如说,给每个文档设置一个“friends_weight”属性,默认值是0,然后临时将文档 123,456,789(当前用户的朋友推荐的)的这个属性设置为1,最后用这个值进行相关度计算。
原型: function SetSelect ( $clause )
设置select子句,列出具体要取出的属性以及要计算并取出的expressions。子句的语法模仿了SQL。于版本0.9.9-rc1引入。
SetSelect()于标准SQL查询中SELECT和FROM之间的部分非常相近。它允许你指定要取出哪些属性(列),以及在这些列上要计算和 取出哪些表达式。与SQL语言的区别是,表达式必须用关键字AS给每个表达式取一个别名,别名必须是有效的标识符(由字母和数字组成)。在SQL里面可以 这样做,但是不是强制的。Sphinx强制必须有别名,以便计算结果总是可以以一个“正常”的名字在结果集中返回,或者在其他子句中引用,等等。
其他方面基本上等同于SQL。支持星号(“*”),支持函数,支持任意数目的表达式。计算出的表达式可以用于排序、过滤和分组,这与其他常规属性相同。
从版本0.9.9-rc2开始,允许使用GROUP BY的时候使用聚集函数(AVG(), MIN(), MAX(), SUM())。
表达式排序(Section 4.5, “SPH_SORT_EXPR 模式”)和地表距离计算函数(Section 6.4.5, “SetGeoAnchor (设置地表距离锚点)”)现在的内部实现就是这种表达式计算机制,分别使用“魔法名字”“@expr”和“@geodist”。
$cl->SetSelect ( "*, @weight+(user_karma+ln(pageviews))*0.1 AS myweight" ); $cl->SetSelect ( "exp_years, salary_gbp*{$gbp_usd_rate} AS salary_usd, IF(age>40,1,0) AS over40" ); $cl->SetSelect ( "*, AVG(price) AS avgprice" );
原型: function SetMatchMode ( $mode )
设置全文查询的匹配模式,见Section 4.1, “匹配模式”中的描述。参数必须是一个与某个已知模式对应的常数。
警告: (仅PHP)查询模式常量不能包含在引号中,那给出的是一个字符串而不是一个常量:
$cl->SetMatchMode ( "SPH_MATCH_ANY" ); // INCORRECT! will not work as expected $cl->SetMatchMode ( SPH_MATCH_ANY ); // correct, works OK
原型: function SetRankingMode ( $ranker )
设置评分模式。目前只在SPH_MATCH_EXTENDED2这个匹配模式中提供。参数必须是与某个已知模式对应的常数。
Sphinx默认计算两个对最终匹配权重有用的因子。主要是查询词组与文档文本的相似度。其次是称之为BM25的统计函数,该函数值根据关键字文档中的频率(高频导致高权重)和在整个索引中的频率(低频导致高权重)在0和1之间取值。
然而,有时可能需要换一种计算权重的方法——或者可能为了提高性能而根本不计算权值,结果集用其他办法排序。这个目的可以通过设置合适的相关度计算模式来达到。
已经实现的模式包括:
原型: function SetSortMode ( $mode, $sortby="" )
设置匹配项的排序模式,见Section 4.5, “排序模式”中的描述。参数必须为与某个已知模式对应的常数。
警告: (仅PHP)查询模式常量不能包含在引号中,那给出的是一个字符串而不是一个常量:
$cl->SetSortMode ( "SPH_SORT_ATTR_DESC" ); // INCORRECT! will not work as expected $cl->SetSortMode ( SPH_SORT_ATTR_ASC ); // correct, works OK
原型: function SetWeights ( $weights )
按在索引中出现的先后顺序给字段设置权重。 不推荐使用, 建议使用 SetFieldWeights()。
原型: function SetFieldWeights ( $weights )
按字段名称设置字段的权值。参数必须是一个hash(关联数组),该hash将代表字段名字的字符串映射到一个整型的权值上。
字段权重影响匹配项的评级。Section 4.4, “权值计算” 解释了词组相似度如何影响评级。这个调用用于给不同的全文数据字段指定不同于默认值的权值。
给定的权重必须是正的32位整数。最终的权重也是个32位的整数。默认权重为1。未知的属性名会被忽略。
目前对权重没有强制的最大限制。但您要清楚,设定过高的权值可能会导致出现32位整数的溢出问题。例如,如果设定权值为10000000并在扩展模式中进行搜索,那么最大可能的权值为10M(您设的值)乘以1000(BM25的内部比例系数,参见Section 4.4, “权值计算”, “权值计算”)再乘以1或更多(词组相似度评级)。上述结果最少是100亿,这在32位整数里面没法存储,将导致意想不到的结果。
原型: function SetIndexWeights ( $weights )
设置索引的权重,并启用不同索引中匹配结果权重的加权和。参数必须为在代表索引名的字符串与整型权值之间建立映射关系的hash(关联数组)。默认值是空数组,意思是关闭带权加和。
当在不同的本地索引中都匹配到相同的文档ID时,Sphinx默认选择查询中指定的最后一个索引。这是为了支持部分重叠的分区索引。
然而在某些情况下索引并不仅仅是被分区了,您可能想将不同索引中的权值加在一起,而不是简单地选择其中的一个。SetIndexWeights()
允许您这么做。当开启了加和功能后,最后的匹配权值是各个索引中的权值的加权合,各索引的权由本调用指定。也就是说,如果文档123在索引A被找到,权值是2,在B中也可找到,权值是3,而且您调用了SetIndexWeights ( array ( "A"=>100, "B"=>10 )
)
,那么文档123最终返回给客户端的权值为2*100+3*10 = 230。
原型: function SetIDRange ( $min, $max )
设置接受的文档ID范围。参数必须是整数。默认是0和0,意思是不限制范围。
此调用执行后,只有ID在$min
和$max
(包括$min
和$max
)之间的文档会被匹配。
原型: function SetFilter ( $attribute, $values, $exclude=false )
增加整数值过滤器。
此调用在已有的过滤器列表中添加新的过滤器。$attribute
是属性名。$values
是整数数组。$exclude
是布尔值,它控制是接受匹配的文档(默认模式,即$exclude
为false时)还是拒绝它们。
只有当索引中$attribute
列的值与$values
中的任一值匹配时文档才会被匹配(或者拒绝,如果$exclude
值为true)
原型: function SetFilterRange ( $attribute, $min, $max, $exclude=false )
添加新的整数范围过滤器。
此调用在已有的过滤器列表中添加新的过滤器。$attribute
是属性名, $min
、$max
定义了一个整数闭区间,$exclude
布尔值,它控制是接受匹配的文档(默认模式,即$exclude
为false时)还是拒绝它们。
只有当索引中$attribute
列的值落在$min
和 $max
之间(包括$min
和 $max
),文档才会被匹配(或者拒绝,如果$exclude
值为true)。
原型: function SetFilterFloatRange ( $attribute, $min, $max, $exclude=false )
增加新的浮点数范围过滤器。
此调用在已有的过滤器列表中添加新的过滤器。$attribute
是属性名, $min
、$max
定义了一个浮点数闭区间,$exclude
必须是布尔值,它控制是接受匹配的文档(默认模式,即$exclude
为false时)还是拒绝它们。
只有当索引中$attribute
列的值落在$min
和 $max
之间(包括$min
和 $max
),文档才会被匹配(或者拒绝,如果$exclude
值为true)。
原型: function SetGeoAnchor ( $attrlat, $attrlong, $lat, $long )
为地表距离计算设置锚点,并且允许使用它们。
$attrlat
和 $attrlong
是字符串,分别指定了对应经度和纬度的属性名称。$lat
和 $long
是浮点值,指定了锚点的经度和纬度值,以角度为单位。
一旦设置了锚点,您就可以在您的过滤器和/或排序表达式中使用"@geodist"
特殊属性。Sphinx将在每一次全文检索中计算给定经纬度与锚点之前的地表距离,并把此距离附加到匹配结果上去。SetGeoAnchor
和索引属性数据中的经纬度值都是角度。而结果会以米为单位返回,因此地表距离1000.0代表1千米。一英里大约是1609.344米。
原型: function SetGroupBy ( $attribute, $func, $groupsort="@group desc" )
设置进行分组的属性、函数和组间排序模式,并启用分组(参考Section 4.6, “结果分组(聚类)”中的描述)。
$attribute
是字符串,为进行分组的属性名。$func
为
常数,它指定内建函数,该函数以前面所述的分组属性的值为输入,目前的可选的值为:
SPH_GROUPBY_DAY、SPH_GROUPBY_WEEK、 SPH_GROUPBY_MONTH、
SPH_GROUPBY_YEAR、SPH_GROUPBY_ATTR 。 $groupsort
是控制分组如何排序的子句。其语法与Section 4.5,
“SPH_SORT_EXTENDED 模式”中描述的相似。
分组与SQL中的GROUP BY子句本质上相同。此函数调用产生的结果与下面伪代码产生的结果相同。
SELECT ... GROUP BY $func($attribute) ORDER BY $groupsort
注意,影响最终结果集中匹配项顺序的是$groupsort
。排序模式(见Section 6.3.3, “SetSortMode (设置排序模式)”)影响每个分组内的顺序,即每组内哪些匹配项被视为最佳匹配。比如,组之间可以根据每组中的匹配项数量排序的同时每组组内又根据相关度排序。
从版本 0.9.9-rc2 开始, 聚合函数 (AVG(), MIN(), MAX(), SUM()) 可以在GROUP BY时被 SetSelect() API 调用。
原型: function SetGroupDistinct ( $attribute )
设置分组中需要计算不同取值数目的属性名。只在分组查询中有效。
$attribute
是包含属性名的字符串。每个组的这个属性的取值都会被储存起来(只要内存允许),其后此属性在此组中不同值的总数会被计算出来并返回给客户端。这个特性与标准SQL中的COUNT(DISTINCT)
子句类似。因此如下Sphinx调用
$cl->SetGroupBy ( "category", SPH_GROUPBY_ATTR, "@count desc" ); $cl->SetGroupDistinct ( "vendor" );
等价于如下的SQL语句:
SELECT id, weight, all-attributes, COUNT(DISTINCT vendor) AS @distinct, COUNT(*) AS @count FROM products GROUP BY category ORDER BY @count DESC
在上述示例伪代码中,SetGroupDistinct()
调用只与COUNT(DISINCT vendor)
对应。GROUP BY
,ORDER By
和COUNT(*)
子句则与SetGroupBY()
调用等价。两个查询都会在每类中返回一个匹配的行。除了索引中的属性,匹配项还可以包含每类的匹配项计数和每类中不同来源
ID的计数。
原型: function Query ( $query, $index="*", $comment="" )
连接到searchd
服务器,根据服务器的当前设置执行给定的查询,取得并返回结果集。
$query
是查询字串,$index
是包含一个或多个索引名的字符串。一旦发生一般错误,则返回假并设置GetLastError()
信息。若成功则返回搜索的结果集。 此外, $comment
将被发送到查询日志中搜索部分的前面,这对于调试是非常有用的。目前,注释的长度限制为128个字符以内。
$index
的默认值是"*"
,意思是对全部本地索引做查询。索引名中允许的字符包括拉丁字母(a-z),数字(0-9),减号(-)和下划线(_),其他字符均视为分隔符。因此,下面的示例调用都是有效的,而且会搜索相同的两个索引:
$cl->Query ( "test query", "main delta" ); $cl->Query ( "test query", "main;delta" ); $cl->Query ( "test query", "main, delta" );
给出多个索引时的顺序是有意义的。如果同一个文档ID的文档在多个索引中找到,那么权值和属性值会取最后一个索引中所存储的作为该文档ID的权值和属性值,用于排序、过滤,并返回给客户端(除非用SetIndexWeights()显式改变默认行为)。因此在上述示例中,索引“delta”中的匹配项总是比索引“main”中的更优先。
如果搜索成功,Query()
返回的结果集包含找到的全部匹配项中的一部分(根据SetLimits()之设定)和与查询相关的统计数据。结果集是hash(仅PHP,其他语言的API可能使用其他数据结构)
,包含如下键和值:
searchd
报告的错误信息(人类可读的字符串)。若无错误则为空字符串。searchd
报告的警告信息(人类可读字符串)。若无警告则为空串。需要指出的是 Query()
索执行的操作,与没有中间步骤的 AddQuery()
和 RunQueries()
相同 ; 它类似一次单独的AddQuery()
调用,紧跟一次相应的RunQueries()
调用,然后返回匹配的第一个数组元素 (从第一次,也是仅有的一次查询返回)。
原型: function AddQuery ( $query, $index="*", $comment="" )
向批量查询增加一个查询。$query
为查询串。$index
为包含一个或多个索引名的字符串。 此外, 如果提供了$comment
,它 将被发送到查询日志中搜索部分的前面,这对于调试是非常有用的。目前,注释的长度限制为128个字符以内。返回RunQueries()返回的数组中的一个下标。
批量查询(或多查询)使searchd
能够进行可能的内部优化,并且无论在任何情况下都会减少网络连接和进程创建方面的开销。相对于单独的查询,批量查询不会引入任何额外的开销。因此当您的Web页运行几个不同的查询时,一定要考虑使用批量查询。
例如,多次运行同一个全文查询,但使用不同的排序或分组设置,这会使searchd
仅运行一次开销昂贵的全文检索和相关度计算,然后在此基础上产生多个分组结果。
有时您不仅需要简单地显示搜索结果,而且要显示一些与类别相关的计数信息,例如按制造商分组后的产品数目,此时批量查询会节约大量的开销。若无批量 查询,您会必须将这些本质上几乎相同的查询运行多次并取回相同的匹配项,最后产生不同的结果集。若使用批量查询,您只须将这些查询简单地组成一个批量查 询,Sphinx会在内部优化掉这些冗余的全文搜索。
AddQuery()
在内部存储全部当前设置状态以及查询,您也可在后续的AddQuery()
调用中改变设置。早先加入的查询不会被影响,实际上没有任何办法可以改变它们。下面是一个示例:
$cl->SetSortMode ( SPH_SORT_RELEVANCE ); $cl->AddQuery ( "hello world", "documents" ); $cl->SetSortMode ( SPH_SORT_ATTR_DESC, "price" ); $cl->AddQuery ( "ipod", "products" ); $cl->AddQuery ( "harry potter", "books" ); $results = $cl->RunQueries ();
用上述代码,第一个查询会在“documents”索引上查询“hello
world”并将结果按相关度排序,第二个查询会在“products”索引上查询“ipod”并将结果按价格排序,第三个查询在“books”索引上搜
索“harry potter”,结果仍按价格排序。注意,第二个SetSortMode()
调用并不会影响第一个查询(因为它已经被添加了),但后面的两个查询都会受影响。
此外,在AddQuery()
之前设置的任何过滤,都会被后续查询继续使用。因此,如果在第一个查询前使用SetFilter()
,则通过AddQuery()
执行的第二个查询(以及随后的批量查询)都会应用同样的过滤,除非你先调用ResetFilters()
来清除过滤规则。同时,你还可以随时加入新的过滤规则
AddQuery()
并不修改当前状态。也就是说,已有的全部排序、过滤和分组设置都不会因这个调用而发生改变,因此后续的查询很容易地复用现有设置。
AddQuery()
返回RunQueries()
结果返回的数组中的一个下标。它是一个从0开始的递增整数,即,第一次调用返回0,第二次返回1,以此类推。这个方便的特性使你在需要这些下标的时候不用手工记录它们。
原型: function RunQueries ()
连接到searchd,运行由AddQuery()
添加的全部查询,获取并返回它们的结果集。若发生一般错误(例如网络I/O失败)则返回假并设置GetLastError()
信息。若成功则返回结果集的简单数组。
该数组中的每一个结果集都跟Query()
返回的结果集完全相同。
注意,批量查询请求自身几乎总是成功——除非有网络错误、正在进行索引轮换,或者其他导致整个查询无法被处理的因素。
然而其中的单个的查询很可能失败。此时与之对应的结果集只包含一个非空的"error"
信息,而没有关于匹配或查询的统计信息。在极端情况下,批量查询中的所有单个查询可能都失败。但这仍然不会导致报告一般错误,因为API已经成功地连接到searchd
,提交了批量查询并得到返回结果——但每个结果集都只包含特定的错误信息。
原型: function ResetFilters ()
清除当前设置的过滤器。
通常此调用在使用批量查询的时候会用到。您可能需要为批量查询中的不同查询提供不同的过滤器,为达到这个目的,您需要调用ResetFilters()
然后用其他调用增加新的过滤器。
原型: function BuildExcerpts ( $docs, $index, $words, $opts=array() )
该函数用来产生文档片段(摘要)。连接到searchd
,要求它从指定文档中产生片段(摘要),并返回结果。
$docs
为包含各文档内容的数组。$index
为包含索引名字的字符串。给定索引的不同设置(例如字符集、形态学、词形等方面的设置)会被使用。$words
为包含需要高亮的关键字的字符串。它们会按索引的设置被处理。例如,如果英语取词干(stemming)在索引中被设置为允许,那么即使关键词是“shoe”,“shoes”这个词也会被高亮。从版本0.9.9-rc1开始,关键字可以包含通配符,与查询支持的star-syntax类似。$opts
为包含其他可选的高亮参数的hash表:
失败时返回false。成功时返回包含有片段(摘要)字符串的数组。
原型: function UpdateAttributes ( $index, $attrs, $values )
立即更新指定文档的指定属性值。成功则返回实际被更新的文档数目(0或更多),失败则返回-1。
$index
为待更新的(一个或多个)索引名。$attrs为属性名字符串的数组,其所列的属性会被更新。$attrs
为hash表,$values
表的键为文档ID,$values
表的值为新的属性值的简单数组。
$index
既可以是一个单独的索引名,也可以是一个索引名的列表,就像Query()
的参数。与Query()
不同的是不允许通配符,全部待更新的索引必须明确指出。索引名列表可以包含分布式索引。对分布式索引,更新会同步到全部代理上。
只有在docinfo=extern
这个存储策略下才可以运行更新。更新非常快,因为操作完全在内存中进行,但它们也可以变成持久的,更新会在searchd
干净关闭时(收到SIGTERM信号时)被写入磁盘。在额外限制条件下,MVA属性也可以被更新,参见mva_updates_pool详细了解。
使用示例
$cl->UpdateAttributes ( "test1", array("group_id"), array(1=>array(456)) ); $cl->UpdateAttributes ( "products", array ( "price", "amount_in_stock" ), array ( 1001=>array(123,5), 1002=>array(37,11), 1003=>(25,129) ) );
第一条示例语句会更新索引“test1”中的文档1,设置“group_id”为456.第二条示例语句则更新索引“products”中的文档 1001,1002和1003。文档1001的“price”会被更新为123,“amount_in_stock”会被更新为5;文档 1002,“price”变为37而“amount_in_storage”变为11,等等。
原型: function BuildKeywords ( $query, $index, $hits )
根据指定索引的符号化(tokenizer)方式的设置,从查询中抽取关键词,也可以同时返回每个关键词出现次数的统计信息。返回一个数组,其元素是一些字典,每个字典包含一个关键字的信息。
$query
是抽取关键字的目标。$index
是某个索引的名字,系统会使用这个索引的符号化(tokenizer)设置,关键词出现次数的统计信息也从这个索引中得出。$hits
是一个布尔值,它指定了是否需要返回关键词出现此处的信息。
使用示例:
$keywords = $cl->BuildKeywords ( "this.is.my query", "test1", false );
原型: function EscapeString ( $string )
查询语言分析器将某些字符理解成特殊操作符,这个函数对字符串中的那些有特殊意义的字符进行转义。返回转义后的字符串。
$string
是待转义的字符串。
表面上看这个函数是多余的,因为可以很容易地在可能调用这个函数的程序里实现这个转义功能。然而这些特殊字符的集合可能随着时间而改变,因此理应提供一个API调用来完成这个功能,并保证任何时候都可以正确地转义全部特殊字符。
使用示例:
$escaped = $cl->EscapeString ( "escaping-sample@query/string" );
SphinxSE是一个可以编译进MySQL 5.x版本的MySQL存储引擎,它利用了该版本MySQL的插件式体系结构。SphinxSE不能用于MySQL 4.x系列,它需要MySQL 5.0.22或更高版本;或MySQL 5.1.12或更高版本。
尽管被称作“存储引擎”,SphinxSE自身其实并不存储任何数据。它其实是一个允许MySQL服务器与searchd
交互并获取搜索结果的嵌入式客户端。所有的索引和搜索都发生在MySQL之外。
显然,SphinxSE的适用于:
在Windows系统下,如果运行的是MySQL5.0.x版本,您可以直接下载预先编译好的支持SphinxSE的mysqld-nt.exe程序,下载mysql-5.0.45-sphinxse-0.9.8-win32.zip解压后,用其中的mysqld-nt.exe替换掉MySQL5.0.x中的mysqld-nt.exe,即可启用SphinxSE功能。
在其他情况下,您需要得到一份MySQL的源码,并重新编译MySQL。MySQL源码(mysql-5.x.yy.tar.gz)可在dev.mysql.com网站获得。
针对某些版本的MySQL,Sphinx 网站提供了包含支持SphinxSE的打过补丁tarball压缩包。将这些文件解压出来替换原始文件,就可以配置(configure)、构建(build)以生成带有内建Shpinx支持的MySQL了。
如果网站上没有对应版本的tarball,或者由于某种原因无法工作,那您可能需要手工准备这些文件。您需要一份安装好的GUN Autotools框架(autoconf,automake和libtool)来完成这项任务。
注意:,因为MySQL 5.0.x 和MySQL 5.1.x存储引擎和插件实现方式的不同,安装SphinxSE的方法也是不同的,请仔细查看以下对应版本的安装步骤。
如果使用我们事先做好的打过补丁的tarball,那请跳过步骤1-3。
将 sphinx.5.0.yy.diff
补丁文件复制到MySQL源码目录并运行
patch -p1 < sphinx.5.0.yy.diff
如果没有与您的MySQL版本完全匹配的.diff文件,请尝试一个最接近版本的.diff文件。确保补丁顺利应用,没有rejects。
sh BUILD/autorun.sh
sql/sphinx
目录,并把Sphinx源码目录中mysqlse
目录下的全部文件拷贝到这个目录。示例:
mkdir -p /root/builds/mysql-5.0.24/sql/sphinx cp -R /root/builds/sphinx-0.9.7/mysqlse/* /root/builds/mysql-5.0.24/sql/sphinx
./configure --with-sphinx-storage-engine
make make install
如果使用我们事先做好的打过补丁的tarball,那请跳过步骤1-3:
storage/sphinx
目录,并将Sphinx源码目录中的mysqlse
目录下的全部文件拷贝到这个目录。示例:
mkdir -p /root/builds/mysql-5.1.14/storage/sphinx cp -R /root/builds/sphinx-0.9.7/mysqlse/* /root/builds/mysql-5.1.14/storage/sphinx
sh BUILD/autorun.sh
./configure --with-plugins=sphinx
make make install
SHOW ENGINES
查询,这会显示一个全部可用引擎的列表。Sphinx应该出现在这个列表中,而且在“Support”列上显示“YES”:
mysql> show engines; +------------+----------+-------------------------------------------------------------+ | Engine | Support | Comment | +------------+----------+-------------------------------------------------------------+ | MyISAM | DEFAULT | Default engine as of MySQL 3.23 with great performance | ... | SPHINX | YES | Sphinx storage engine | ... +------------+----------+-------------------------------------------------------------+ 13 rows in set (0.00 sec)
要通过SphinxSE搜索,您需要建立特殊的ENGINE=SPHINX的“搜索表”,然后使用SELECT语句从中检索,把全文查询放在WHERE子句中。
让我们从一个create语句和搜索查询的例子开始:
CREATE TABLE t1 ( id INTEGER UNSIGNED NOT NULL, weight INTEGER NOT NULL, query VARCHAR(3072) NOT NULL, group_id INTEGER, INDEX(query) ) ENGINE=SPHINX CONNECTION="sphinx://localhost:9312/test"; SELECT * FROM t1 WHERE query='test it;mode=any';
搜索表前三列(字段)的类型必须是INTEGER UNSINGED
(或者 BIGINT
),INTEGER
(或者 BIGINT
)和VARCHAR
(或者 TEXT
),这三列分别对应文档ID,匹配权值和搜索查询。这前三个列的映射关系是固定的,你不能忽略这三列中的任何一个,或者移动其位置,或者改变其类型。搜索查询列必须被索引,其他列必须无索引。列的名字会被忽略,所以可以任意命名。
除此之外,其他列(字段)的类型必须是INTEGER
、TIMESTAMP
、BIGINT
、VARCHAR
或者FLOAT
之一。它们必须与Sphinx结果集中提供的属性按名称绑定,即它们的名字必须与sphinx.conf
中指定的属性名一一对应。如果Sphinx搜索结果中没有某个属性名,该列的值就为NULL
.
特殊的“虚拟”属性名也可以与SphinxSE列绑定。但特殊符号@
用_sph_
代替。例如,要取得@group
和@count
虚属性,列名应使用_sph_group
和_sph_count
。
可以使用字符串参数CONNECTION
来指定用这个表搜索时的默认搜索主机、端口号和索引。如果CREATE TABLE
中没有使用连接(connection)串,那么默认使用索引名“*”(搜索所有索引)和localhost:9312。连接串的语法如下:
CONNECTION="sphinx://HOST:PORT/INDEXNAME"
默认的连接串也可以日后改变:
ALTER TABLE t1 CONNECTION="sphinx://NEWHOST:NEWPORT/NEWINDEXNAME";
也可以在查询中覆盖全部这些选项。
如例子所示,查询文本和搜索选项都应放在WHERE子句中对query列的限制中(即第三列),选项之间用分号分隔,选项名与选项值用等号隔开。可以指定任意数目的选项。可用的选项如下:
... WHERE query='test;sort=attr_asc:group_id'; ... WHERE query='test;sort=extended:@weight desc, group_id asc';
... WHERE query='test;index=test1;'; ... WHERE query='test;index=test1,test2,test3;';
... WHERE query='test;weights=1,2,3;';
# only include groups 1, 5 and 19 ... WHERE query='test;filter=group_id,1,5,19;'; # exclude groups 3 and 11 ... WHERE query='test;!filter=group_id,3,11;';
# include groups from 3 to 7, inclusive ... WHERE query='test;range=group_id,3,7;'; # exclude groups from 5 to 25 ... WHERE query='test;!range=group_id,5,25;';
... WHERE query='test;maxmatches=2000;';
... WHERE query='test;groupby=day:published_ts;'; ... WHERE query='test;groupby=attr:group_id;';
... WHERE query='test;groupsort=@count desc;';
... WHERE query='test;indexweights=idx_exact,2,idx_stemmed,1;';
非常重要的注意事项:让Sphinx来对结果集执行排序、过滤和切片(slice)要比提高最大匹配项数量然后在MySQL端用WHERE、ORDER BY和LIMIT子句完成对应的功能来得高效得多。这有两方面的原因。首先,Sphinx对这些操作做了一些优化,比MySQL效率更高一些。其次,searchd可以打包更少的数据,SphinxSE也可以传输和解包更少的数据。
从版本0.9.9-rc1开始,除了结果集,额外的查询信息可以用SHOW ENGINE SPHINX STATUS
语句获得:
mysql> SHOW ENGINE SPHINX STATUS; +--------+-------+-------------------------------------------------+ | Type | Name | Status | +--------+-------+-------------------------------------------------+ | SPHINX | stats | total: 25, total found: 25, time: 126, words: 2 | | SPHINX | words | sphinx:591:1256 soft:11076:15945 | +--------+-------+-------------------------------------------------+ 2 rows in set (0.00 sec)
查询状态信息可以通过状态变量名来访问。值得提醒的是,访问这些信息不需要超级用户权限。
mysql> SHOW STATUS LIKE 'sphinx_%'; +--------------------+----------------------------------+ | Variable_name | Value | +--------------------+----------------------------------+ | sphinx_total | 25 | | sphinx_total_found | 25 | | sphinx_time | 126 | | sphinx_word_count | 2 | | sphinx_words | sphinx:591:1256 soft:11076:15945 | +--------------------+----------------------------------+ 5 rows in set (0.00 sec)
可以对SphinxSE搜索表和其他引擎的表之间使用JOIN,以下是一个例子,例中“documents”来自example.sql
:
mysql> SELECT content, date_added FROM test.documents docs -> JOIN t1 ON (docs.id=t1.id) -> WHERE query="one document;mode=any"; +-------------------------------------+---------------------+ | content | docdate | +-------------------------------------+---------------------+ | this is my test document number two | 2006-06-17 14:04:28 | | this is my test document number one | 2006-06-17 14:04:28 | +-------------------------------------+---------------------+ 2 rows in set (0.00 sec) mysql> SHOW ENGINE SPHINX STATUS; +--------+-------+---------------------------------------------+ | Type | Name | Status | +--------+-------+---------------------------------------------+ | SPHINX | stats | total: 2, total found: 2, time: 0, words: 2 | | SPHINX | words | one:1:2 document:2:2 | +--------+-------+---------------------------------------------+ 2 rows in set (0.00 sec)
从版本0.9.9-rc2开始,SphinxSE提供了一个UDF函数,允许用户通过MySQL创建摘要。这个功能的作用与API调用BuildExcerprts的功能非常相似,但可以通过MySQL+SphinxSE来访问。
提供这个UDF的二进制文件叫做sphinx.so
,当安装SphinxSE本身的时候,这个文件会自动地被创建,并且安装到合适的位置。 但如果由于某种原因它没能自动安装,那就请在创建SphinxSE的目录中寻找sphinx.so
文件,并把它拷贝到你的MySQL实例的plugins目录下。然后用下面语句来注册这个UDF:
CREATE FUNCTION sphinx_snippets RETURNS STRING SONAME 'sphinx.so';
函数的名字必须是sphinx_snippets,而不能随便取名。函数的参数表必须如下:
原型: function sphinx_snippets ( document, index, words, [options] );
Documents和words这两个参数可以是字符串或者数据库表的列。Options参数(额外选项)必须这样指定:‘值’ AS 选项名
。关于支持的所有选项,可以参见API调用BuildExcerprts()。只有一个选项不被API支持而只能用于UDF,这个选项叫做'sphinx'
,用于指定searchd的位置(服务器和端口)。
使用示例:
SELECT sphinx_snippets('hello world doc', 'main', 'world', 'sphinx://192.168.1.1/' AS sphinx, true AS exact_phrase, '[b]' AS before_match, '[/b]' AS after_match) FROM documents; SELECT title, sphinx_snippets(text, 'index', 'mysql php') AS text FROM sphinx, documents WHERE query='mysql php' AND sphinx.id=documents.id;
很不幸,Sphinx还没有达到100%无bug(尽管我们正向这个目标努力),因此您可能偶尔遇到些问题。
对于每个问题的报告越详细越好,这很重要——因为要想修复bug,我们必须重现bug并调试它,或者根据您提供的信息来推断出产生bug的原因。因此在此提供一些如何报告bug的指导。
如果Sphinx构建失败,请您按照以下步骤进行:
mysql-devel
包已经安装)mysql_config gcc --version uname -a
configure
脚本或者gcc
给出的错误信息(只需错误信息本身,不必附上整个构建日志)如果Sphinx已经成功构建并能运行,但运行过程中出现了问题,请您按照以下步骤进行:
mysql --version gcc --version uname -a
make distclean ./configure --with-debug make install killall -TERM searchd
searchd
有关,请在bug报告中提供searchd.log
和query.log
中的相关条目;searchd
有关,请尝试在console模式下运行它并检查它是否因断言失败而退出。
./searchd --console
如果任何一个程序因断言(assertions)失败而退出,崩溃或停止响应,您可以额外生成一个内存转储文件并检查它。
ulimit
命令启用它:
ulimit -c 32768
kill -SEGV
强制退出并获得内存转储:
kill -SEGV HANGED-PROCESS-ID
gdb
检查转储文件,查看backtrace
gdb ./CRASHED-PROGRAM-FILE-NAME CORE-DUMP-FILE-NAME (gdb) bt (gdb) quit
提示: HANGED-PROCESS-ID(停止响应的进程ID), CRASHED-PROGRAM-FILE-NAME(崩溃程序的文件名) and CORE-DUMP-FILE-NAME(核心转储文件的文件名)应该被换成具体的数字和文件名。例如,一次对停止响应的searchd的调试会话看起来 应该像下面这样:
# kill -SEGV 12345 # ls *core* core.12345 # gdb ./searchd core.12345 (gdb) bt ... (gdb) quit
注意ulimit
并不是整个服务器范围的,而是仅影响当前的shell会话。因此您不必还原任何服务器范围的限制——但是一旦重新登陆,您就需要再次设置ulimit
。
核心内存转储文件会存放在当前工作目录下(Sphinx的各个程序不会改变工作目录),因此它们就在那。
不要立刻删除转储文件,从它里面可能获得更多有用的信息。您不需要把这个文件发送给我们(因为调试信息与您的系统本身紧密相关),但我们可能会向您询问一些与之相关的问题。
数据源类型。必须选项,无默认值。 已知的类型包括 mysql
, pgsql
, mssql
, xmlpipe
and xmlpipe2
, 以及 odbc
.
在CoreSeek的分发版本中,数据源类型还可以是python
,从而得以启用Python数据源支持。
所有其他与数据源相关的选项都依赖于这个选项指定的源类型。与SQL数据源(即MSSQL、MySQL和PostgreSQL)相关的选项以“sql_”开头,而与xmlpipe和xmlpipe2数据源相关的选项则以“xmlpipe_”开头。 除了xmlpipe
是默认支持外,其他数据源类型的支持是有前提条件的;依赖与您的设置和已安装的数据库客户端库文件,它们可能被支持或者不被支持。例如,mssql
仅在Windows系统提供支持。odbc
在Windows系统上是原生支持,而在Linux系统上通过UnixODBC
library支持。
在CoreSeek的分发版本中,python
通过Python提供支持,在安装了Pythin的Windows系统和Linux系统上都可以支持。
type = mysql
要连接的SQL服务器主机地址。必须选项,无默认值。仅对SQL数据源(mysql
, pgsql
, mssql
)有效。
最简单的情形下,Sphinx与MySQL或PostgreSQL服务器安装在同一台主机上,此时您只须设置为localhost即可。注 意,MySQL客户端库根据主机名决定是通过TCP/IP还是UNIX socket连接到服务器。一般来说,“localhost”使之强制使用UNIX socket连接(这是默认的也是推荐的模式),而“127.0.01”会强制使用TCP/IP。细节请参考 MySQL manual。
sql_host = localhost
要连接的SQL服务器的IP端口。可选选项,默认值为mysql
端口3306,pgsql
端口5432。仅适用于SQL数据源(mysql
, pgsql
, mssql
)。注意,此选项是否实际被使用依赖于sql_host选项。
sql_port = 3306
连接到本地SQL服务器时使用的UNIX socket名称。可选选项,默认值为空(使用客户端库的默认设置)。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
在Linux上,通常是/var/lib/mysql/mysql.sock
。 而在FreeBSD上通常是/tmp/mysql.sock
。注意此选项是否实际被使用依赖与sql_host的设置。
sql_sock = /tmp/mysql.sock
MySQL客户端的连接标志(connection flags)。可选选项,默认值为0(不设置任何标志)。仅适用于mysql
数据源。
此选项必须包含各标志相加所得的整型值。此整数将被原样传递给mysql_real_connect() 。 可用的标志在mysql_com.h中列举。下面列举的是几个与索引相关的标志和它们的值:
例如,标志2080(2048+32)代表同时使用压缩和SSL,32768代表仅使用新的身份验证。起初这个选项是为了在indexer
和mysql
位
于不同主机的情况下使用压缩协议而引入的。尽管降低了网络带宽消耗,但不管在理论上还是在现实中,在1Gbps的链路上启用压缩很可能恶化索引时间。然而
在100Mbps的连输上启用压缩可能会明显地改善索引时间(有报告说总的索引时间降低了20-30%)。根据您网络的连接情况,您获得的改善程度可能会
有所不同。
mysql_connect_flags = 32 # enable compression
连接MySQL服务器时使用的SSL认证选项。可选参数,默认值是空串(即不使用SSL认证)。 Applies to mysql
source type only.
这些指令用来在indexer
和MySQL之间建立安全的SSL连接。关于怎样建立认证机制和设置MySQL服务器的信息可以参考MySQL文档。仅适用于mysql
数据源。
mysql_ssl_cert = /etc/ssl/client-cert.pem mysql_ssl_key = /etc/ssl/client-key.pem mysql_ssl_ca = /etc/ssl/cacert.pem
要连接的ODBC DSN。必须选项,没有默认值。 仅适用于odbc
数据源。
ODBC DSN(数据源名字,Data Source Name)指定了连接ODBC数据源时使用的认证选项(主机地址,用户名,密码等)。具体的格式与ODBC的具体驱动有关。
odbc_dsn = Driver={Oracle ODBC Driver};Dbq=myDBName;Uid=myUsername;Pwd=myPassword
取前查询(pre-fetch query),或预查询(pre-query)。多值选项,可选选项,默认为一个空的查询列表。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
多值意思是您可以指定多个预查询。它们在the main fetch query之前执行,而且会严格按照在配置文件中出现的顺序执行。预查询的结果会被忽略。
预查询在很多时候有用。它们被用来设置字符编码,标记待索引的记录,更新内部计数器,设置SQL服务器连接选项和变量等等。
也许预查询最常用的一个应用就是用来指定服务器返回行时使用的字符编码。这必须与Sphinx期待的编码相同(在charset_type 和charset_table 选项中设置)。以下是两个与MySQL有关的设置示例:
sql_query_pre = SET CHARACTER_SET_RESULTS=cp1251 sql_query_pre = SET NAMES utf8
对于MySQL数据源,在预查询中禁用查询缓冲(query cache)(仅对indexer连接)是有用的,因为索引查询一般并会频繁地重新运行,缓冲它们的结果是没有意义的。这可以按如下方法实现:
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre = SET NAMES utf8 sql_query_pre = SET SESSION query_cache_type=OFF
获取文档的主查询。必须的选项,无默认选项。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
只能有一个主查询。它被用来从SQL服务器获取文档(文档列表)。可以指定多达32个全文数据字段(严格来说是在sphinx.h中定义的SPH_MAX_FIELDS个)和任意多个属性。所有既不是文档ID(第一列)也不是属性的列的数据会被用于建立全文索引。
文档ID必须是第一列,而且必须是唯一的正整数值(不能是0也不能是负数),既可以是32位的也可以是64位的,这要根据Sphinx是如何被构建的,默认情况下文档ID是32位的,但在运行configure
脚本时指定--enable-id64
选项会打开64位文档ID和词ID的支持。
sql_query = \ SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, \ title, content \ FROM documents
分区查询设置。可选选项,默认为空。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
设置这个选项会启用文档的区段查询(参看Section 3.7, “区段查询”)。分区段查询有助于避免在索引大量数据时发生MyISAM表臭名昭著的死锁问题。(同样有助于解决其他不那么声名狼藉的问题,比如大数据集上的性能下降问题,或者InnoDB对多个大型读事务(read transactions)进行序列化时消耗额外资源的问题。)
此选项指定的查询语句必须获取用于分区的最小和最大文档ID。它必须返回正好两个整数字段,先是最小ID然后是最大ID,字段的名字会被忽略。
当启用了分区段查询时,sql_query要求包括$start
和 $end
宏(因为重复多次索引整个表显然是个错误)。注意,$start
.. $end
所指定的区间不会重叠,因此不会在查询中删除ID正好等于$start
或$end
的文档。Section 3.7,
“区段查询”中的例子解释了这个问题,注意大于等于或小于等于比较操作是如何被使用的。
sql_query_range = SELECT MIN(id),MAX(id) FROM documents
区段查询的步进。可选选项,默认为1024。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
仅当启用ranged queries 时有效。用sql_query_range 取得的文档ID区间会被以这个不小的间隔步数跳跃遍历。例如,如果取得的最小和最大ID分别是12和3456,而间隔步数是1000,那么indexer会用下面这些值重复调用几次sql_query:
sql_range_step = 1000
用于得到Kill-list的查询。可选选项,默认为空(不设定查询)。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。 Introduced in version 0.9.9-rc1.
这个查询返回的结果集应该只有一列,每行是一个文档ID。返回的这些文档ID将被存储在一个索引里。根据查询中提到的索引的顺序,一个索引的kill-list会抑制来自其他索引的结果。这个设计的目的是要帮助用户实现在现有索引上的删除或者更新,而不用重建索引(甚至根本不用访问这个索引),尤其是为了结果解决“幽灵结果”问题。
让我们来分析一个实际的例子。假设我们有两个索引,‘main’和‘delta’。假设文档2、3和5在上一次重建索引‘main’的时候就被删除 了,而文档7和文档11则被更新了(即他们的文字内容发生了变化)。假设在建立索引‘main’的时候,关键字‘test’在所有这些提到的文档中都出现 了。而当我们建立索引‘delta’的时候文档7中也出现了关键字‘test’,但是文档11中不再有关键字‘test’了。现在我们重新建立索引 ‘delta’,然后以合适的顺序(较旧的排在较新的之前)对这两个索引进行检索:
$res = $cl->Query ( "test", "main delta" );
首先,我们要正确地处理删除的情况。结果集合不应该包含文档2、3或5。其次,我们也要避免出现幽灵结果。如果我们不做点什么,文档11就会出现在搜索结果中。因为它会被在‘main’中查到(但在‘delta’中查不到它),并出现在最终的结果集合中,除非我们做点什么防止这种情况的发生。
Kill-list,或者缩写成K-list就是我们要做的。附加在‘delta’索引上的Kill-list会屏蔽掉前面所有各索引中检索到的特定行,在这个例子中,也就是‘main’中的行。因此,想要得到预期的结果,我们应该将更新了的和删除了的文档ID都放进Kill-list。
sql_query_killlist = \ SELECT id FROM documents WHERE updated_ts>=@last_reindex UNION \ SELECT id FROM documents_deleted WHERE deleted_ts>=@last_reindex
声明无符号整数属性(attribute)。可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
被声明的列的值必须在32位无符号整型可表示的范围内。超出此范围的值也会被接受,但会溢出。例如-1会变成 2^32-1 或者说4,294,967,295。
您可以在属性名后面附加“:BITCOUNT”(见下面的示例)以便指定整型属性的位数。属性小于默认32位(此时称为位域)会有损性能。但它们在外部存储(extern storage)模式下可以节约内存:这些位域被组合成32位的块存储在.spa
属性数据文件中。如果使用内联存储(inline
storage),则位宽度的设置会被忽略。
sql_attr_uint = group_id sql_attr_uint = forum_id:9 # 9 bits for forum_id
声明布尔属性(attribute)。可声明同一类型的多个不同名称的属性,可选项。仅适用于SQL数据源(mysql和pgsql)。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
等价于用sql_attr_uint声明为1位。
sql_attr_bool = is_deleted # will be packed to 1 bit
64位整数属性(attribute)声明。多个值(可以同时声明多个属性),可选选项。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。 注意,与sql_attr_uint不同,这些值是有符号的。于版本0.9.9-rc1引入。
sql_attr_bigint = my_bigint_id
声明UNIX时间戳属性(attribute)。可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
这个列的值必须是UNIX格式的时间戳,即32位无符号整数表示的自格林尼治平时1970年1月1日午夜起过去的秒数。时间戳在内部是按整数值存储 和处理的。但除了将时间戳按整数使用,还可以对它们使用多种与日期相关的函数——比如时间段排序模式,或为分组(GROUP BY)抽取天/星期/月/年。注意MySQL中的DATE和DATETIME列类型不能直接作为时间戳使用,必须使用UNIX_TIMESTAMP函数将这些列做显式转换。
sql_attr_timestamp = UNIX_TIMESTAMP(added_datetime) AS added_ts
声明字符串序数属性(attribute )。可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
这个属性类型(简称为字串序数)的设计是为了允许按字符串值排序,但不存储字符串本身。对字串序数做索引时,字符串值从数据库中取出、暂存、排序然后用它们在该有序数组中的序数代替它们自身,因此字串序数是个整型,对它们的大小比较与在原字串上做字典序比较结果相同。
早期版本上,对字串序数做索引可能消耗大量的RAM。自r1112起,字串序数的积累和排序也可在固定大小的内存中解决了(代价是额外的临时磁盘空间),并受 mem_limit 设置限制。
理想中字符串可以根据字符编码和本地字符集(locale)排序。例如,如果已知字符串为KOI8R编码下的俄语字串,那么对字节 0xE0,0xE1和0xE2排序结果应为0xE1,0xE2和0xE0,因为0xE0在KOI8R中代表的字符明显应在0xE1和0xE2之后。但很不 幸,Sphinx目前不支持这个功能,而是简单地按字节值大小排序。
请注意,这里的序号是每个索引根据自身数据计算的,因此在同时读取多个索引事实无法同时保留正确的顺序进行合并的。处理后的字符串被替换为处理时其 在索引中的序列号,但是不同的索引具有不同的字符串集。例如,如果'main'索引包含字符串"aaa", "bbb", "ccc", 直到 "zzz",它们将会被分别分配数值为1,2,3,直到26。但是'delta'如果仅包含"zzz",则会被分配数值1。那么在合并后,该顺序将被打 乱。不幸的是,在不存储原始字符串的情况下,这个问题无法解决(一旦存储原始字符串,序号将没有任何用处了)。
sql_attr_str2ordinal = author_name
声明浮点型属性 attribute 。 可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
属性值按单精度32位IEEE754格式存储。可表示的范围大约是1e-38到1e+38。可精确表示的小数大约是7位。浮点属性的一个重要应用是存储经度和纬度值(以角度为单位),经纬度值在查询时的地表距离计算中有用。
sql_attr_float = lat_radians sql_attr_float = long_radians
声明多值属性(Multi-valued attribute ,MVA)). 可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
简单属性每篇文档只允许一个值。然而有很多情况(比如tags或者类别)需要将多个值附加给同一个属性,而且要对这个属性值列表做过滤或者分组。
声明格式如下(用反斜线只是为了清晰,您仍可以在一行之内完成声明):
sql_attr_multi = ATTR-TYPE ATTR-NAME 'from' SOURCE-TYPE \ [;QUERY] \ [;RANGE-QUERY]
其中
sql_attr_multi = uint tag from query; SELECT id, tag FROM tags sql_attr_multi = uint tag from ranged-query; \ SELECT id, tag FROM tags WHERE id>=$start AND id<=$end; \ SELECT MIN(id), MAX(id) FROM tags
后取查询。可选项,默认值为空。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
此查询在sql_query成功执行后立即执行。如果取后取查询产生了错误,该错误被当作警告被报告,但索引不会因此终止。取后查询的结果会被忽略。注意当取后查询执行时索引还尚未完成,而后面的索引仍然可能失败。因此在这个查询中不应进行任何永久性的更新。例如,不应在此查询中更新辅助表中存储的最近成功索引的文档ID值,请在后索引查询(post-index query )中操作。
sql_query_post = DROP TABLE my_tmp_table
后索引查询。可选项,默认值为空。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
此查询在索引完全成功结束后执行。如果此查询产生错误,该错误会被当作警告报告,但索引不会因此而终止。该查询的结果集被忽略。此查询中可以使用宏$maxid
,它会被扩展为索引过程中实际得到的最大的文档ID。
sql_query_post_index = REPLACE INTO counters ( id, val ) \ VALUES ( 'max_indexed_id', $maxid )
分区查询的间隔时间(throttling),单位是毫秒。可选选项,默认值为0(无间隔时间)。 仅适用于SQL数据源(mysql
, pgsql
, mssql
)。
此选项旨在避免indexer对数据库服务器构成了太大的负担。它会使indexer在每个分区查询的步之后休眠若干毫秒。休眠无条件执行,并在取结果的查询之前执行。
sql_ranged_throttle = 1000 # sleep for 1 sec before each query step
文档信息查询。 可选选项,默认为空。 仅对 mysql
数据源有效。
仅被命令行搜索所用,用来获取和显示文档信息,目前仅对MySQL有效,且仅用于调试目的。此查询为每个文档ID获取CLI搜索工具要显示的文档信息。 它需要包含$id
宏,以此来对应到查询的文档的ID。
sql_query_info = SELECT * FROM documents WHERE id=$id
调用xmlpipe流提供者的Shell命令。必须选项。仅对xmlpipe
和 xmlpipe2
数据源有效。
指定的命令会被运行,其输出被当作XML文档解析。具体格式描述请参考 Section 3.8, “xmlpipe 数据源” or Section 3.9, “xmlpipe2 数据源” 。
xmlpipe_command = cat /home/sphinx/test.xml
声明xmlpipe数据字段。可声明同一类型的多个不同名称的属性,可选项。仅对xmlpipe2
数据源有效。参考 Section 3.9, “xmlpipe2 数据源”.
xmlpipe_field = subject xmlpipe_field = content
声明xmlpipe整型属性。可声明同一类型的多个不同名称的属性,可选项。仅对xmlpipe2
数据源有效。语法与 sql_attr_uint相同。
xmlpipe_attr_uint = author
声明xmlpipe布尔型属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2
数据源有效。语法与 sql_attr_bool相同。
xmlpipe_attr_bool = is_deleted # will be packed to 1 bit
声明xmlpipe UNIX时间戳属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2
数据源有效。语法与 sql_attr_timestamp相同。
xmlpipe_attr_timestamp = published
声明xmlpipe字符序数属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2
数据源有效。语法与 sql_attr_str2ordinal相同。
xmlpipe_attr_str2ordinal = author_sort
声明xmlpipe浮点型属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2
数据源有效。语法与 sql_attr_float相同。
xmlpipe_attr_float = lat_radians xmlpipe_attr_float = long_radians
声明xmlpipe MVA属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2
数据源有效。
这个选项为xmlpipe2流声明一个MVA属性标签。该标签的内容会被试图解析成一个整型值的列表(数组),此列表构成一个MVA属性值,这与把MVA属性的数据源设置为“字段”时sql_attr_multi分析SQL列内容的方式类似。
xmlpipe_attr_multi = taglist
在Sphinx端进行UTF-8验证和过滤,防止XML分析器因为碰上非UTF-8文档而犯疯卡死。可选选项,默认值为0。只适用于xmlpipe2数据源。 仅对xmlpipe2
数据源有效。
在某些特定情况下很难甚至不可能保障输入的xmlpipe2文档体都是完美有效一致的UTF-8编码。例如,输入流中可能溜进一些特定国家的单字节 编码文本。Libexpat这个XML分析器非常脆弱,遇到这种情况就会停止工作。UTF-8修复(UTF-8 fixup)功能能让这种情况得到避免。当启动了修复选项的时候,Sphinx会对输入留进行预处理,其后再传给XML分析器,其间非法的UTF-8序列 全部被替换成空格。
xmlpipe_fixup_utf8 = 1
标志位,代表是否使用MS SQL的windows身份认证。布尔型,可选选项,默认值是0(假)。只适用于mssql
数据源。于版本0.9.9-rc1引入。
这个选项指出在连接到MS SQL Server时时候使用现在正登录的windows账户的凭据作来进行身份验证。注意当searchd
作为服务运行时,账户的用户名可能与安装这个服务的账户不同。
mssql_winauth = 1
MS SQL编码类型标志位。布尔型,可选选项,默认值是0(假)。只适用于mssql
数据源。于版本0.9.9-rc1引入。
这个选项指出在对MS SQL Server进行查询时,是使用Unicode还是单字节数据。这个标志位必须与charset_type指令同步,也就是说,要索引Unicode数据,则既要设置charset_type选项(设为‘utf-8’),又要设置数据源的mssql_unicode
选项(设为1)。多说一句:MS
SQL实质上返回UCS-2编码的数据,而不是UTF-8,但Sphinx可以自动处理这个情况。
mssql_unicode = 1
使用zlib(即gnuzip)来解压(unpack,deflate)的列。多个值,可选选项,默认值是列的空列表。仅适用于SQL数据源(mysql
, pgsql
, mssql
)。于版本0.9.9-rc1引入。
indexer
会使用标准zlib算法(称作deflate,gunzip
也实现了这个算法)对这个选项指定的那些列进行解压缩。当建立索引的动作发生在数据库所在机器以外的机器时,这个选项会降低数据库的负载,并节约网络带宽。要想使用这个特性,就必须保证在建立时zlib和zlib-devel都是可用的。
unpack_zlib = col1 unpack_zlib = col2
使用MySQL UNCOMPRESS()算法解压的列。多个值,可选选项,默认值是列的空列表。仅适用于SQL数据源(mysql
, pgsql
, mssql
)。于版本0.9.9-rc1引入。
indexer
会使用MySQL
COMPRESS()和UNCOMPRESS()使用的修改过的zlib算法对这个选项指定的那些列进行解压缩。
当建立索引的动作发生在数据库所在机器以外的机器时,这个选项会降低数据库的负载,并节约网络带宽。要想使用这个特性,就必须保证在建立时zlib和
zlib-devel都是可用的。
unpack_mysqlcompress = body_compressed unpack_mysqlcompress = description_compressed
用于UNCOMPRESS()解压后数据的缓冲区大小。可选选项,默认值是16M。于版本0.9.9-rc1引入。
当使用unpack_mysqlcompress选项时,由于实现方法本质上的限制,不可能减小缓冲区大小方面的需求。因此缓冲区必须预先分配好,解压出的数据也不能超过缓冲区大小。这个选项控制这个缓冲区大小值,既可以用于限制indexer
的内存使用,也可以用于在需要的时候使解压非常大的数据变为可能
unpack_mysqlcompress_maxsize = 1M
索引类型。可选选项,默认值为空(索引为简单本地索引)。可用的值包括空字符串或“distributed”
Sphinx支持两种不同的索引类型:本地——在本机上存储和处理,和远程——不仅涉及本地搜索,而且同时通过网络向远程searchd
实例做查询。索引类似选项使您可以选择使用何种索引。索引默认是本地型。指定“distributed”索引类型会运行分布式搜索,参看 Section 4.7,
“分布式搜索”.
type = distributed
向本地索引增加文档源。可以出现多次,必须选项。
为当前索引指定一个从中可以获取文档的文档源。必须至少有一个文档源。可以有多个文档源,任何数据源类型都可接受:即您可以从MySQL服务器中获取一部分数据,从PostgreSQL中获取另一部分,再在文件系统上使用xmlpipe2获取一部分。
然而,对源数据却有一些限制。首先,文档ID必须在所有源的总体上是唯一的。如果这个条件不满足,那可能导致非预期的搜索结果。其次,源的模式必须相同,以便在同一个索引中存储。
数据来源的ID不会被自动存储。因此,为了获知匹配的文档是从哪个数据源中来的,需要手工存储一些额外的信息。通常有两种方法:
source src1 { sql_query = SELECT id*10+1, ... FROM table1 ... } source src2 { sql_query = SELECT id*10+2, ... FROM table2 ... }
source src1 { sql_query = SELECT id, 1 AS source_id FROM table1 sql_attr_uint = source_id ... } source src2 { sql_query = SELECT id, 2 AS source_id FROM table2 sql_attr_uint = source_id ... }
source = srcpart1 source = srcpart2 source = srcpart3
索引文件的路径和文件名(不包括扩展名)。必须选项。
path既包括文件夹也包括文件名,但不包括扩展名。indexer
在产生永久和临时索引文件的最终名字时会附加上不同的扩展名。永久数据文件有几个不同的扩展名,都以“.sp”开头,临时文件的扩展名以“.tmp”开头。如果indexer没有成功地自动删除.tmp*
文件,手工删除是安全的。
以下是不同索引文件所存储的数据种类,供参考:
.spa
存储文档属性(仅在extern docinfo存储模式中使用);.spd
存储每个词ID可匹配的文档ID列表;.sph
存储索引头信息;.spi
存储词列表(词ID和指向.spd
文件的指针);.spm
存储MVA数据;.spp
存储每个词ID的命中(或者说记账,或者词的出现)列表;path = /var/data/test1
文档信息(docinfo)的存储模式。可选选项,默认是“extern”已知的值包括'none', 'extern' 和 'inline'.。
此选项确切定义了文档信息在磁盘和RAM中的物理存储方式。“none”意思是根本不存储文档信息(没有任何属性)。通常并不需要显式设置为
“none”因为当没有配置任何属性时Sphinx会自动选择“none”。“inline”代表文档信息与文档ID列表一同存储在在.spd
文件中。“extern”代表文档信息与文档ID分开(在外部)存储(在.spa
文件中)。
基本上,外部存储的文档信息在查询时必须保持在内存中。这是性能的原因。因此有时候“inline”是唯一的选择。然而这种情况并不多见,文档信息默认是“extern”存储的。深入的探讨和RAM使用的估计请参见Section 3.2, “属性”。
docinfo = inline
已缓冲数据的内存锁定。可选选项,默认为0(不调用mlock())
为提高性能,searchd
将.spa
和.spi
文件预取到内存中,并一直在内存中保存它们的拷贝。但如果一段时间内没有对该索引的搜索,则对这份缓冲的拷贝没有内存访问,而操作系统可能会决定将它交换到磁盘上去。对这些“冷却”了的索引的访问会导致其交换回内存并得到一个较大的延迟。
将mlock选项设置为1会使Sphinx使用mlock(2)系统调用将存储上述缓冲了的数据的系统内存锁定,这将避免内存交换(详情参见man 2 mlock)。mlock(2)是特权调用,因此可能需要searchd
以root账户运行或通过其他办法赋予足够的权限。如果mlock()失败会发出警告,但索引会继续进行。
mlock = 1
词形处理器的列表。可选选项,默认为空(不使用任何词形处理器)。
词形处理器可以将待索引的词从各种形态变成基本的规则的形态。例如,英语词干提取器(English stemmer)可以将“dogs”和“dog”都变成“dog”,这使搜索这两个词的结果都相同。
内置的词形处理器包括英语词干提取器,俄语词干提取器(支持UTF-8和Windows-1251编码),Soundex和Metaphone。后面两个会将词替换成特殊的语音编码,这会使发音相近的词表示形式相同。Snowball 项目的libstemmer 库提供的额外词干提取器可以通过在编译期对configure
脚本使用--with-libstemmer
选项来启用。内建的英语和俄语词干提取器要比它们在libstemmer中的对应物模块运行更快,但它们的结果可能略有不同,因为内建的版本基于较旧的版本。Metaphone基于Double
Metaphone算法实现。
在morphology
选项中可使用的内建值包括
“none”,“stem_en”,“stem_ru”,“stem_enru”,
“soundex”和“metaphone”。libstemmer提供的额外值格式为“libstemmer_XXX”,XXX指libstemmer
算法的代号。(完整列表参见libstemmer_c/libstemmer/modules.txt
)
可以指定多个词干提取器(以逗号分隔)。这些提取器按列出的顺序应用于输入词串,整个处理会在第一个真正修改了原词的词干提取器之后停止。另外,当wordforms 特性启用时,词会现在词形字典中查询,如果词典中有对应的条目,那么词干提取器干脆不会被使用。换个说法,wordforms选项可以用来补充指定词干提取器的例外情况。
morphology = stem_en, libstemmer_sv
启用词干化的最小词长。可选选项,默认为1(对任何词都进行词干化)。于版本0.9.9-rc1引入。
词干化方法并不完美,有时会产生用户不想要的结果。例如,如果用英语的Porter stemmer词干化算法处理关键词“gps”,得到的结果是“gp”,显然这是不对的。min_stemming_len
这个特性允许根据词的长度来决定是否跳过词干化,即不对较短的词进行词干化。注意,词长等于这个选项设置的值的词会被词干化。因此要避免对3个字符长的关键词进行词干化,必须指定这个选项的值为4。要活的更细粒度的控制,请参考wordforms这个特性。
min_stemming_len = 4
停用词文件列表(空格分隔)。可选选项,默认为空。
停用词是不被索引的词。停用词表一般包括最常用的高频词,因为它们对搜索结果没有多大帮助却消耗很多处理资源。
可以指定多个文件名,用空格分隔。所有文件都会被载入。停用词文件的格式是简单的纯文本。其编码必须与charset_type选项所指定的索引编码相匹配。文件数据会根据charset_type选项的设置进行切分,因此您可以使用与待索引数据相同的分隔符。词干提取器(stemmers)也会在停用词文件的分析中使用。
尽管停用词不会被索引,它们却影响关键词的位置。例如,假设“the”是一个停用词,文档1包含一行“in office”,而文档2包含“in the office”。将“in office”作为确切词组搜索则只会得到文档1,虽然文档2里的the是停用的。
stopwords = /usr/local/sphinx/data/stopwords.txt stopwords = stopwords-ru.txt stopwords-en.txt
词形字典。 可选选项,默认为空。
词形字典在输入文档根据charset_table切 碎后使用。本质上,它使您可以将一个词替换成另一个。这通常被用来将不同的词形变成一个单一的标准形式(即将词的各种形态如 “walks”,“walked”,“walking”变为标准形式“walk”)。也可以用来实现取词根的例外情况,因为词形字典中可以找到的词不会经 过词干提取器的处理。
索引和搜索中的输入词都会利用词典做规则化。因此要使词形字典的更改起作用,需要重新索引并重启searchd
。
Sphnix的词形支持被设计成可以很好地支持很大的字典。它们轻微地影响索引速度:例如,1M个条目的字典会使索引速度下降1.5倍。搜索速度则
完全不受影响。额外的内存占用大体上等于字典文件的大小,而且字典是被多个索引共享的,即如果一个50MB的词形字典文件被10个不同的索引使用了,那么
额外的searchd
内存占用就是大约50MB。
字典文件的格式是简单的纯文本。每行包括一个源词形和一个目标词形,编码应与charset_type选项所指定的完全相同,二者用大于号分隔。文件载入时会经过charset_table选项指定的规则的处理。因此基本上在大小写是否敏感这个问题上它是与待索引的全文数据相同的,即通常是大小写无关的。一下是个文件内容的例子:
walks > walk walked > walk walking > walk
我们提供了一个spelldump
工具,它可以帮您从ispell
和 MySpell
(OpenOffice提供)格式的.dict
和.aff
字典文件生成Sphinix可接受的格式。
从版本0.9.9-rc1开始,可以将好几个源词对应到同一个目标词上。由于这个过程作用于符号化之后的结果而不是原始文本,空白字符和标记语言都被忽略。
core 2 duo > c2d e6600 > c2d core 2duo > c2d
wordforms = /usr/local/sphinx/data/wordforms.txt
Token特例文件。 可选选项,默认为空。
对于使用Coreseek的中文用户,这一选项无效。Coreseek为Sphinx贡献的中文分词法内置了Token特例化支持,具体参阅Coreseek MMSeg分词法的文档。不过,值得高兴的是,Token特例化的文件格式两者是同样的。
此选项允许将一个或多个Token(Token中,可以包括在正常情况下会被过滤的字符)映射成一个单独的关键词。exceptions选项与wordforms选项很类似,它们都代表某种映射,但有一些重要的不同点。
这些不同点简要总结如下:
输入文件的格式仍然是纯文本,每行一个分词例外,而行的格式如下:
map-from-tokens => map-to-token
示例文件
AT & T => AT&T AT&T => AT&T Standarten Fuehrer => standartenfuhrer Standarten Fuhrer => standartenfuhrer MS Windows => ms windows Microsoft Windows => ms windows C++ => cplusplus c++ => cplusplus C plus plus => cplusplus
这里全部的记号都是大小写敏感的:它们不会按charset_table选项的规则处理。因此,在上述例外文件下,“At&t”会被分成两个关键字“at”和“t”,因为其中的小写字母。而“AT&T”却被精确匹配并产生一个单独的关键字“AT&T”。
需要注意的是,前述映射文件的目标关键词(右侧)a)总是被解释成一个单独的词,而且b)不仅是大小写敏感的,而且是空白符号敏感的!在上述样例中,查询“ms windows”不会匹配包含“MS Windows”的文档。这个查询会被解释成两个词“ms”和“Windows”。而“MS Windows”映射到的是一个单独的 关键字“ms windows”,包括中间的空格。另一方面“standartenfuhrer”会取回带有“Standarten Fuhrer”或者“Standarten Fuehrer”内容的文档(大写字母必须与此处列出的完全相同),或者关键词本身大小写随意的任何版本,例如“staNdarTenfUhreR”。 (然而“standarten fuhrer”不会匹配。这段文本无法与列出的任何一个例外相匹配,因为大小写不同。因此被索引为两个分开的关键字)
映射源部分的空白符(white space)不会被忽略,但空白符的数量无所谓。任何数量的空白符都匹配已索引的文档或者查询中的任意数量的空白符。例如映射源部分(“=>”左 端)的“AT�&�T”可以匹配“AT��&�T”,不管被映射部分或已索引全文数据中实际有几个空格。根据上述例子中的第一条,上述文 本会作为“AT&T”关键字被索引。 对于使用Coreseek的中文用户,这个特性目前尚不被支持。Coreseek将在后续版本支持这个特性。
exceptions选项也允许特殊字符(这是通用charset_table选项规则的例外(exception),此选项因而得名)。假设您一般不想把“+”当作有效的字符,但仍想搜索一些例外情况,比如“C++”。上述例子正好可以做到这点,完全不管哪些字符在表中,哪些字符不在。
Exceptions选项被应用于原始输入文档和索引、搜索时的查询数据。因此要使文件的改动生效,需要重建索引并重启searchd
。
exceptions = /usr/local/sphinx/data/exceptions.txt
最小索引词长度。可选选项,默认为1(索引任何词)
只有长度不小于这个最小索引词长度的词会被索引。例如,如果min_word_len为4,那么“the”这个词不会被索引,但“they”会。
min_word_len = 4
字符集编码类型。可选选项,默认为“sbcs”。已知的值包括“sbcs”和“utf-8”。 对于使用Coreseek的中文用户,可选的值还可以有“zh_cn.utf-8 ”、“zh_cn.gbk”和“zh_cn.big5”。当设置charset_type值为上面的值时,系统默认您开启了中文分词特性。
不同的编码将它们的内部字符代码映射到特殊字节序列的方法不同。目前两个最常见的方法是单字节编码和UTF-8。它们对应的 charset_type值分别是“sbcs”(代表Single Byte Character Set单字节字符集)和“utf-8”。选定的编码类型会在搜索被使用的任何情况下使用:索引数据时,对索引查询时,产生摘要时,等等。
注意,尽管“utf-8”暗示解码出来的值应按unicode码点数值对待,“sbcs”却对应一系列不同的编码,它们对不同字节值的处理不同,这要在charset_table设置中正确地反应出来。例如,同一个值244(十六进制0xE0)根据使用的是koi-8r还是windows-1251编码而映射到不同的俄语字符。
charset_type = utf-8
接受的字符表和大小写转换规则。可选选项,默认值与charset_type 选项的值有关。 对于使用Coreseek的中文用户,Coreseek 提供的MMseg分词法内置了可接受的字符表,并且用户不可修改。当启用分词功能时,自动开启。
charset_table频繁应用于Sphinx的分词过程,即从文档文本或查询文本中抽取关键字的过程。它控制哪些字符被当作有效字符接受,哪些相反,还有接受了的字符如何转换(例如大小写信息保留还是去除)。
可以把charset_table想成一个对超过100K个Unicode字符中每一个的映射关系的大表(或者一个256个字符的小表,如果你使用 SBCS)。默认每个字符都对应0,这表示它不在关键字中出现,应被视为分隔符。一旦在此表中被提及,字符就映射到另一个字符(通常是它自身或者自身的小 写版本),同时被当作一个可以出现在关键字中的有效字符。
值的格式是逗号分隔的映射列表。两种最简单的映射分别是声明一个字符为有效和将一个简单字符映射为另一个字符。但用这种格式指定整个表会导致其体积臃肿、无法管理。因此提供了一些语法上的快捷方式,用它们可以一次指定一定范围的字符。详细的列表如下:
编码为0到31之间的控制字符总是被视作分隔符。编码32到127的字符即7位ASCII字符可以原样使用在映射中。为避免配置文件的编码问题,8 位ASCII字符和Unicode字符必须以U+xxx形式指定,“xxx”是码点对应的十六进制数。也可以用这个形式编码7位ASCII编码中的特殊字 符,例如用U+20来编码空格符,U+2E来编码句点,U+2C来编码逗号。
# 'sbcs' defaults for English and Russian charset_table = 0..9, A..Z->a..z, _, a..z, \ U+A8->U+B8, U+B8, U+C0..U+DF->U+E0..U+FF, U+E0..U+FF # 'utf-8' defaults for English and Russian charset_table = 0..9, A..Z->a..z, _, a..z, \ U+410..U+42F->U+430..U+44F, U+430..U+44F
忽略字符表。 可选选项,默认为空。
有些字符,如软断字符(U+00AD),不是仅仅要当作分隔符,而且应该被完全忽略。例如,如果“-”只是不在charset_table里,那么 “abc-def”会被当作两个关键字“abc”和“def”来索引。相反,如果将“-”加到ignore_char列表中,那么相同的文本会被当作一个 单独的关键字“abcdef”索引。
此选项的语法与 charset_table相同,但只允许声明字符,不允许映射它们。另外,忽略的字符不能出现在charset_table里。
ignore_chars = U+AD
索引的最小前缀长度。可选选项,默认为0(不索引前缀)。
前缀索引使实现“wordstart*”形式的通配符成为可能(通配符语法的细节请参考 enable_star 选项)。当最小前缀长度被设置为正值,indexer除了关键字本身还会索引所有可能的前缀(即词的开头部分)。太短的前缀(小于允许的最小值)不会被索引。
例如,在min_prefix_len=3设置下索引关键字“example”会导致产生5个索引项“exa”, “exam”, “examp”, “exampl”和该词本身。对这个索引搜索“exam”会得到包含“example”的文档,即使该文档中没有“exam”自身。然而,前缀索引会使索 引体积急剧增大(因为待索引关键字增多了很多),而且索引和搜索的时间皆会恶化。
在前缀索引中没有自动的办法可以提高精确匹配(整个词完全匹配)的评分,但有一些技巧可以实现这个功能。首先,可以建立两个索引,一个带有前缀索引,另一个没有,同时在这两个索引中搜索,然后用 SetIndexWeights() 来设置二者的权重。其次,可以启用星号语法并重写扩展模式的查询:
# in sphinx.conf enable_star = 1 // in query $cl->Query ( "( keyword | keyword* ) other keywords" );
min_prefix_len = 3
索引的最小中缀长度。可选选项,默认为0(不索引中缀)。
中缀索引是实现“start*”, “*end”, and “*middle*”等形式的通配符成为可能(通配符语法的细节请参考 enable_star 选项)。当最小中缀长度设置为正值,indexer除了对关键字本身还会对所有可能的中缀(即子字符串)做索引。太短的中缀(短于允许的最小长度)不会被索引。例如,在min_infix_len=2设置下索引关键字“test”会导致产生6个索引项 "te", "es", "st", "tes", "est"等中缀和词本身。对此索引搜索“es”会得到包含“test”的文档,即使它并不包含“es”本身。然而,中缀索引会使索引体积急剧增大(因为 待索引关键字增多了很多),而且索引和搜索的时间皆会恶化。
在中缀索引中没有自动的办法可以提高精确匹配(整个词完全匹配)的评分,但可以使用与 prefix indexes 选项中相同的技巧。
min_infix_len = 3
做前缀索引的字段列表。可选选项,默认为空(所有字段均为前缀索引模式)。
因为前缀索引对索引和搜索性能均有影响,可能需要将它限制在某些特定的全文数据字段:例如,对URL提供前缀索引,但对页面内容不提供。prefix_fields指定哪些字段要提供前缀索引,其他字段均会使用普通模式。值的格式是逗号分隔的字段名字列表。
prefix_fields = url, domain
做中缀索引的字段列表。可选选项,默认为空(所有字段均为中缀索引模式)。
与 prefix_fields选项类似,但限制的是哪些字段做中缀索引。
infix_fields = url, domain
允许前缀/中缀索引上的星号语法(或称通配符)。可选选项,默认为0(不使用通配符),这是为了与0.9.7版本的兼容性。已知的值为0和1。
此特性启用搜索前缀或中缀索引时的“星号语法”,或者说通配符语法。仅影响搜索,因此要使改变生效只须重启 searchd
,而不需要重新索引。
默认值为0,意思是禁止星号语法,所有关键字都根据索引时的 min_prefix_len 和 min_infix_len settings设置被视为前缀或者中缀。取值1的意思是星号(“*”)可以用在关键字的前面或后面。星号与零个或多个字符匹配。
例如,假设某索引启用了中缀索引,且enable_star值为1。搜索过程按如下工作:
enable_star = 1
n-gram索引的n-gram长度。可选选项,默认为0(禁用n-gram索引)已知的值是0和1(其他长度尚未实现) 对于使用Coreseek的中文用户,在启用了中文分词的情况下,本节内容可忽略。
n-gram提供对未分词CJK(Chinese, Japanse, Koreasn中日韩)文本的基本支持。CJK搜索的问题在于词与词之前没有清晰的界限。理想中,文本可以通过一个称作分词程序(segmenter)的 特殊程序的过滤,之后分隔符即被加入到适当位置。然而分词过程缓慢而易错,因此通常会转而索引连续的一组N个字符,或称n-gram。
启用此特性,CJK字符流会被当作n-gram索引。例如,如果输入文本为“ABCDEF”(A到F均代表CJK字符) ,而此选项设置的长度为1,那它们会被当作“A B C D E F”而索引。(如果此选项设置的长度是2,那会产生“AB BC CD DE EF”,但目前仅支持1)。只有那些在 ngram_chars 选项表中列出的字符会这样分割,其他不受影响。
注意,如果搜索查询是已分词的,即单独的词之间有分隔符分隔,那么在扩展模式中将这些词放入引号中搜索会得到正确的匹配结果,即使文档没有分词。例如,假设原查询为“BC DEF”,在应用程序端用引号将索引包起来,看起来是“BC” “DEF”(包括引号),这个查询被传给Sphinx并在其内部分割成1-gram,查询变成“B C” “D E F”,仍然包括作为词组查询操作符的引号。该查询会匹配正确的文本,即使文本中没有相应的分隔符。
即使搜索查询没有分词,Sphinx也可以返回较好的结果,这要感谢基于词组的相关度计算:它会使相近的词组匹配(在n-gram中CJK词相当于多个字符的词匹配)排在前面。
ngram_len = 1
n-gram字符列表。 可选选项,默认为空。 对于使用Coreseek的中文用户,在启用了中文分词的情况下,本节内容可忽略。
与 ngram_len选项联用,此列表定义了从中抽取n-gram的字符序列。其他字符组成的词不受n-gram索引特性的影响。值的格式与charset_table相同。
ngram_chars = U+3000..U+2FA1F
词组边界符列表。 可选选项,默认为空。
此列表控制哪些字符被视作分隔不同词组的边界,每到一个这样的边界,其后面的词的“位置”值都会被加入一个额外的增量,可以借此用近似搜索符来模拟词组搜索。语法与 charset_table选项相似,但没有字符之间的映射关系,而且这些词组边界符不能重复出现在其他任何设置选项中。
自每个词组边界起,后面的词的“位置”都会被加入一个额外的增量(由 phrase_boundary_step定 义)。这使通过近似搜索符实现词组搜索成为可能:不同词组中的词之间的距离肯定大于phrase_boundary_step,因此相似距离小于 phrase_boundary_step的近似搜索其实是在搜索在一个词组范围内出现了全部给定查询词的情况,相当于词组搜索。
只有词组边界符后面紧跟着一个分隔符时,词组边界才被激活,这是为了避免S.T.A.L.K.E.R 或 URLs 等缩写被错当成若干个连续的词组(因为“.”属于词组边界符)。
phrase_boundary = ., ?, !, U+2026 # horizontal ellipsis
词组边界上词位置的增量。可选选项,默认为0。
在词组边界上,当前词位置会加上此选项设置的额外增量。详细请参考 phrase_boundary 选项。
phrase_boundary_step = 100
是否从输入全文数据中去除HTML标记。可选标记,默认为0。已知值包括0(禁用)和1(启用)。
此特性对 xmlpipe
数据源无效(建议升级到 xmlpipe2 )。这个去除HTML标记的模块应该很好地工作于正确格式化的HTML和XHTML,但就像大多数浏览器一样,对于格式错误的文本(例如带有无法配对的<和>的HTML)可能产生不希望的输出。
只有HTML标签和HTML注释会被删除。要同时删除标签的内容(例如要删除内嵌的脚本),请参考 html_remove_elements 选项。标签名没有限制,即任何看起来像有效的标签开头、结束或者注释的内容都会被删除。
html_strip = 1
去除HTML标记时要索引的标记语言属性列表。可选选项,默认为空(不索引标记语言属性)。
指定被保留并索引的HTML标记语言属性,即使其他HTML标记被删除。格式是对每个标记列举可以索引的属性,请看下例:
html_index_attrs = img=alt,title; a=title;
HTML元素列表,不仅这些元素本身会被删除,它们的中间包括的文字内容也会被删除。可选选项,默认为空串(不删除任何元素的内容)。
此特性允许删除元素的内容,即在开始标记和结束标记之间的所有东西。用于删除内嵌的脚本或CSS等。短格式的元素(即<br />)被适当地支持,即,这种标记后面的内容不会被删除。
值为逗号分隔的标签名称列表。标签名大小写无关。
html_remove_elements = style, script
分布式索引 distributed index中的本地索引声明。可以出现多次, 可选选项,默认为空。
此设置用于声明分布式索引被搜索时要搜索的本地索引。全部本地索引会被依次搜索,仅使用1个CPU或核。要并行处理,可以配置searchd
查询它自身(细节参考 Section 9.2.28,
“agent” )。可以为每个分布式索引声明多个本地索引。每个本地索引可以在其他分布式索引中多次引用。
local = chunk1 local = chunk2
分布式索引(distributed index)中的远程代理和索引声明。可以出现多次,可选选项,默认为空。
此设置用来声明搜索分布式索引时要搜索的远程代理。代理可以看作网络指针,它指定了主机、端口和索引名。在最基本的情况下,代理可以与远程物理主机对应。更严格的来说,这不一定总是正确:可以将多个代理指向同一台远程主机,甚至指向同一个searchd
实例(以便利用多个CPU或核)
值的格式如下:
agent = specification:remote-indexes-list specification = hostname ":" port | path
“hostname”是远程主机名,“port”是远程TCP端口,而“remote-index-list”是一个逗号分隔的远程索引列表。
全部代理会被并行搜索。然而同一个代理的多个索引是依次搜索的。这使您可以根据硬件来优化配置。例如,如果两个远程索引存储在一个相同的硬盘上,最 好是配置一个带有多个按顺序搜索的索引,避免频繁的磁头寻址。如果这些索引存储在不同的硬盘上,那配置两个代理会更有利,因为这可以使工作完全并行。对于 CPU也是如此,虽然在两个进程间切换对性能的影响比较小而且常常被完全忽略。
在有多个CPU和硬盘的机器上,代理可以指向相同的机器以便并行地使用硬件,降低查询延迟。并不需要为此设置多个searchd
实例,一个实例与自身通信是合法的。以下是一个示例设置,它是为一台有4个CPU的机器准备的,可以并行地使用4个CPU,各处理一个查询:
index dist { type = distributed local = chunk1 agent = localhost:9312:chunk2 agent = localhost:9312:chunk3 agent = localhost:9312:chunk4 }
注意其中一块是本地搜索的,而同一个searchd示例又向本身查询,以便并行地启动其他三个搜索。
agent = localhost:9312:chunk2 # contact itself agent = /var/run/searchd.s:chunk2 agent = searchbox2:9312:chunk3,chunk4 # search remote indexes
分布式索引( distributed index)中声明远程黑洞代理。多个值,可选选项,默认是空。于版本0.9.9-rc1引入。
agent_blackhole
选项使用户可以向远程代理发送“即发即忘”的查询(fire-and-forget queries)。这在调试(或者仅仅是测试)即将投入生产的集群的时候很有用:可以设置一个单独的调试/测试searchd
实例,然后从实际生产中使用的主服务器(master,或称聚集者aggregator)实例向这个测试服务器转发查询请求,但不干扰生产系统的工作。主(master)searchd
会以正常的方式尝试连接和查询黑洞代理,但是它既不会等待也不会处理黑洞代理的反馈。同时,发生在黑洞代理上的全部网络错误也都被忽略。值的格式与普通的 agent 完全相同。
agent_blackhole = testbox:9312:testindex1,testindex2
远程代理的连接超时时间,单位为毫秒。可选选项,默认为1000(即1秒)。
连接到远程代理时,searchd
最多花这些时间等待connet()调用成功完成。如果达到了超时时间connect()仍没有完成,而 and retries 选项是启用的,那么将开始重试。
agent_connect_timeout = 300
远程代理查询超时时间,以毫秒为单位。可选选项,默认为3000(即3秒)。
连接后,searchd
最多花这这些时间等到远程查询完成。这个超时时间与连接超时时间是完全独立的。因此一个远程代理最多能造成的延迟为agent_connection_timeout
与agent_query_timeout
之和。如果超时时间已到,查询不会再重试,同时产生警告。
agent_query_timeout = 10000 # our query can be long, allow up to 10 sec
预先打开全部索引文件还是每次查询时再打开索引。可选选项,默认为0(不预先打开)。
此选项令searchd
在启动时(或轮换索引时)预先开打全部索引文件并在运行过程中保持打开。目前,默认是不预先打开这些文件(此行为可能在未来改变)。预先打开的每个索引文件会占用若干(目前是两个)文件描述符。但每次查询可以节约两个open()
调用而且不会受高负载情况下索引轮换过程中可能发生的微妙的竞争条件(race
condition)的影响。另一方面,当提供很多索引服务(几百到几千)时,必须每次查询时打开索引文件以便节约文件描述符。
这个指令不影响indexer
的任何行为,只对searchd
有用。
preopen = 1
指定是将字典文件(.spi)保持在磁盘上还是将它预先缓冲在内存中。可选选项,默认值是0(预先缓冲在内存里)。于版本0.9.9-rc1引入。
字典文件(.spi)既可以驻留在内存中也可以保持在磁盘上。默认情况下是将整个字典缓冲在内存中。这样做提高性能,但可能带来过大的内存压力,尤其是使用了前缀或中缀的时候。启用ondisk_dict
为每次查询的每个关键词带来一次磁盘I/O操作,但是会减少内存使用。
这个指令不影响indexer
的任何行为,只对searchd
有用。
ondisk_dict = 1
是否启用原地索引倒转(in-place index inversion)。可选选项,默认值是0(使用单独的临时文件)。于版本0.9.9-rc1引入。
inplace_enable
选项极大地减少了建立索引时的磁盘压力,代价是略慢的索引速度(少使用大约两倍的磁盘空间,速度方面能达到原有性能的90-95%)
建立索引的过程有两个主要的阶段。第一个阶段主要是收集、处理文档以及对文档根据关键词进行部分的排序,中间结果被写入到临时文件(.tmp*)
中。第二个阶段则对文档进行完全排序并创建总重的索引文件。因此,重建一个正在应用于生产的索引将导致一个三倍大的磁盘占用峰值:第一倍,中间结果临时文
件,第二,新建的副本,和第三,在一切发生时旧的索引仍然占用一份磁盘空间,以便继续服务。(中间结果的大小与最终索引的大小相当)。对于很大的数据集,
这将是一笔很大的磁盘开销,而inplace_enable
选项用于减少这个开销。一旦启用这个选项,临时文件将被重复利用,最终的数据写回到临时文件中,最后改个名字就可以作为最终结果使用了。然而,这可能导致更多的临时数据块重新分配,因此性能会有一点损失。
这个指令不影响searchd
的任何行为,只对indexer
有用。
inplace_enable = 1
微调原地倒转(In-place inversion)行为的选项。控制预先分配的匹配点列表(hitlist)的空隙的大小。可选选项,默认是0。于版本0.9.9-rc1引入。
这个指令不影响searchd
的任何行为,只对indexer
有用。
inplace_hit_gap = 1M
微调原地倒转(In-place inversion)行为的选项。控制预先分配的文档信息(docinfo)的空隙的大小。可选选项,默认是0。于版本0.9.9-rc1引入。
这个指令不影响searchd
的任何行为,只对indexer
有用。
inplace_docinfo_gap = 1M
微调原地倒转(In-place inversion )行为的选项。控制重定位缓冲区占用索引时的内存的比例。可选选项,默认是0.1。于版本0.9.9-rc1引入。
这个指令不影响searchd
的任何行为,只对indexer
有用。
inplace_reloc_factor = 0.1
微调原地倒转(In-place inversion )行为的选项。控制原地写缓冲占用索引时的内存的比例。可选选项,默认是0.1。于版本0.9.9-rc1引入。
这个指令不影响searchd
的任何行为,只对indexer
有用。
inplace_write_factor = 0.1
是否在索引原关键词的词干化/重映射后的形式的同时也索引原词。可选选项,默认值是0(不索引额外的形式)。于版本0.9.9-rc1引入。
一旦启用,index_exact_words
强制indexer
除了词干化的版本外,将原始的关键字也加入索引。这样做也使查询语言中的精确匹配搜索符可用。这个选项将对索引大小和索引时间带来延迟。然而搜索的性能不会被影响。
index_exact_words = 1
在经过过短的词(比 min_word_len短的词)处后增加位置值。 可选选项,允许的值是0或者1,默认是1。于版本0.9.9-rc1引入。
这个指令不影响searchd
的任何行为,只对indexer
有用。
overshort_step = 1
在经过 停用词 处后增加位置值可选选项,允许的值是0或者1,默认是1。于版本0.9.9-rc1引入。
这个指令不影响searchd
的任何行为,只对indexer
有用。
stopword_step = 1
索引过程内存使用限制。可选选项,默认32M。
这是indexer
不会超越的强制内存限制。可以以字节、千字节(以K为后缀)或兆字节(以M为后缀)为单位。参见示例。当过小的值导致I/O缓冲低于8KB时该限制会自动提高,此值的最低限度依赖于待索引数据的大小。如果缓冲低于256KB,会产生警告。
最大可能的限制是2047M。太低的值会影响索引速度,但256M到1024M对绝大多数数据集(如果不是全部)来说应该足够了。这个值设得太高可
能导致SQL服务器连接超时。在文档收集阶段,有时内存缓冲的一部分会被排序,而与数据库的通信会暂停,于是数据库服务器可能超时。这可以通过提高SQL
服务器端的超时时间或降低 mem_limit
来解决。 在Coreseek的分发版本中,如果使用python
数据源,则在Python部分的处理不会受mem_limit
的限制。
mem_limit = 256M # mem_limit = 262144K # same, but in KB # mem_limit = 268435456 # same, but in bytes
每秒最大I/O操作次数,用于限制I/O操作。可选选项,默认为0(无限制)。
与I/O节流有关的选项。它限制了每秒钟最大的I/O操作(读或写)的次数。值0意思是不加限制。
indexer
在索引时可能导致突发的密集磁盘I/O,因此需要限制它磁盘活动(给同一台机器上运行的其他程序留出一些资源,比如searchd
)。 I/O节流就是用来实现上述功能的。它的工作原理是,在indexer
的连续磁盘I/O操作之间强制增加一个保证的延迟。现代SATA硬盘每秒钟可以执行多达70-100以上次的I/O操作(主要受磁头寻道时间的限制)。将索引I/O限制为上述数值的几分之一可以减轻由索引带来的搜索性能下降。
max_iops = 40
最大允许的I/O操作大小,以字节为单位,用于I/O节流。可选选项,默认为0(不限制)。
与I/O节流有关的选项。它限制indexer
文件I/O操作的单次最大大小。值0代表不加限制。超过限制的读写操作会被分成几个小的操作,并被max_iops 计为多次。在本文写作时,全部I/O操作都被限制在256KB以下(默认的内部缓冲大小),因此大于256KB的max_iosize
值没有任何作用。
max_iosize = 1048576
写缓冲区的大小,单位是字节。可选选项,默认值是1MB。
在建立索引过程中,写缓冲用于写入临时行而最终的索引文件。写缓冲区越大则所需的磁盘写入次数越少。缓冲区使用的内存不计入 mem_limit选项的值。注意对于不同的文件,会分配多个缓冲区(目前最多4个),这会引起内存占用增加。
write_buffer = 4M
指定searchd
监听的IP地址和端口,或UNIX域socket的路径。于版本0.9.9-rc1引入。
一个非正式的listen
语法说明如下:
listen = ( address ":" port | port | path ) [ ":" protocol ]
即,用户可以指定IP地址(或主机名)和端口号,或者仅仅是端口号,或者Unix socket的路径。如果仅指定了端口号而没有地址,那么searchd
会在所有的网络接口上监听。Unix路径都带有一个前导的斜杠”/”
从版本0.9.9-rc2开始,还可以指定一个协议处理器(protocl handler),或者叫监听器(listener),应用于这个socket上的连接。支持的协议值包括‘sphinx’(Sphinx 0.9.x API协议)和mysql41(版本4.1到至少5.1的MySQL使用的协议)。关于MySQL协议的更多细节可以参考 Section 4.9, “MySQL 协议支持与 SphinxQL” 。
listen = localhost listen = localhost:5000 listen = 192.168.0.1:5000 listen = /var/run/sphinx.s listen = 9312 listen = localhost:9306:mysql41
可以有多个listen指令,searchd
会在所有这些指令纸浆的端口和socket上监听,以备用户连接。如果没有找到listen
指令,服务器会在所有的网络接口上用默认端口(9312)监听
在Windows上不支持Unix socket。
要绑定的接口IP地址。可选项,默认为0.0.0.0(即在所有接口上监听)。 不推荐, 建议使用 listen 。
address
设置指定searchd
在哪个接口上绑定、监听和接受输入的网络连接。默认值为0.0.0.0,意思是在所有接口上监听。目前不能指定多个接口。
address = 192.168.0.1
查询日志文件名。可选项,默认为空(不记录查询日志)。全部搜索查询会被记录在此文件中。其格式在Section 4.8, “ searchd
查询日志格式”中描述
query_log = /var/log/query.log
子进程的最大数量(或者说,并行执行的搜索的数目)。可选项,默认为0,不限制。
用来控制服务器负载。任何时候不可能有比此设置值更多的搜索同时运行。当达到限制时,新的输入客户端会被用临时失败(SEARCH_RETRY)状态码驳回,同时给出一个声明服务器已到最大连接限制的消息。
max_children = 10
searchd
进程ID文件名。必选项。
PID文件会在启动时重建(并锁定)。主守护进程运行时它含有该进程的ID,而当守护进程退出时该文件会被删除。这个选项是必须的,因为Sphinx在内部使用它做如下事:检查是否已有一个searchd
示例;停止searchd
;通知searchd
应该轮换索引了。也可以被各种不同的外部自动化脚本所利用。
pid_file = /var/run/searchd.pid
守护进程在内存中为每个索引所保持并返回给客户端的匹配数目的最大值。可选选项,默认值为1000。
引入此选项是为了控制和限制内存使用,max_matches
设置定义了搜索每个索引时有多少匹配项会保存在内存中。每个找到的匹配项都会被处理,但只有它们中最佳的N个会在内存中保持并最终返回给客户端。假设索引中包括2000000个当前查询的匹配项,你几乎总是不需要它们中的全部。
通常您需要扫描它们并根据某种条件(即按相关度排序、或者价格、或者其他什么)选出最好的那些,比如500个,并以在页面上显示20到100项。只跟踪最
好的500个匹配要比保持全部的2000000个匹配项大大地节约内存和CPU,之后可以对这些最佳匹配排序,然后丢弃除了要在页面上要显式的20项之外
的结果。max_matches
控制“最佳N个匹配”中的N。
此参数明显影响每个查询消耗的内存和CPU。1000到10000的值通常就可以满足需求,但更高的值要小心使用。粗心地把max_matches
增加到1000000意味着searchd
被迫为每一个查询分配1M条匹配项的缓冲。这会明显增大查询的内存消耗,有时会明显影响性能。
特别注意!此限制还可在另一个地方指定。max_matches
可以通过对应的API调用实时降低,该调用的默认值也是1000。因此要使应用程序获取超过1000个匹配结果,必须修改配置文件,重启searchd,再用SetLimits()调用设置合适的限制。还要注意,API调用设置的限制不能大于.conf文件中的设置,这是为了预防恶意的或错误的请求。
max_matches = 10000
防止 searchd
轮换在需要预取大量数据的索引时停止响应。可选选项,默认为1(启用无缝(seamless)轮换)。
索引可能包含某些需要预取到内存中的数据。目前.spa
, .spi
和 .spm
文件会被完全预取到内存中(它们分别包含属性数据,MVA数据和关键字索引)。若无无缝轮换,轮换索引时会尽量使用较小的内存,并如下工作:
searchd
等待目前正在运行的查询结束;searchd
恢复为新索引提供查询服务。然而,如果有大量的属性或字典数据,那么预调数据的步骤可能消耗大量的时间——预调1.5GB的文件可能需要几分钟的时间。
当启用了无缝轮换,轮换按如下工作:
无缝轮换以轮换过程中更大的峰值内存消耗为代价(因为当预调新索引时.spa/.spi/.spm
数据的新旧拷贝需要同时保持在内存中)。平均内存耗用不变。
seamless_rotate = 1
用UpdateAttributes()
实时更新文档属性时,所产生的变化首先写入到这些属性在内存中的一份拷贝中(必须将docinfo
设置成extern
)。其后,一旦searchd
正常关闭(通过发送SIGTERM
信号),这些变化才写入磁盘。于版本0.9.9-rc1中引入。
从版本0.9.9-rc1开始,可以令searchd
每隔一段时间就将变化写回磁盘,防止丢失这些变化。这个间隔时间通过attr_flush_period
选项设置,单位是秒。
默认值是0,即关闭隔一段时间就将变化写回磁盘的特性,但是正常关闭时的写回不被关闭。
attr_flush_period = 900 # persist updates to disk every 15 minutes
对 ondisk_dict 指令的全局的默认值。 可选选项,默认值是0(将字典预先缓冲到内存)。于版本0.9.9-rc1中引入。
这个选项用于为当前使用的这份searchd
正在提供服务的所有索引指定ondisk_dict选项的默认值。如果某个索引的这个选项做了显式设定,那么这个设定覆盖上述实例级的默认设置,这种机制提供了细粒度的控制。
ondisk_dict_default = 1 # keep all dictionaries on disk
网络通讯时允许的最大的包的大小。这个限制既对来自客户端的查询包有效,也对分布式环境下远程代理返回的响应包有效。只用于内部校验,不直接影响内存占用和性能。可选选项,默认值是8M。于版本0.9.9-rc1引入。
max_packet_size = 32M
用于多值属性MVA更新的存储空间的共享池大小。可选选项,默认大小是1M。于版本0.9.9-rc1引入。
这个设置控制用于存储多值属性MVA更新后的值共享存储池的大小。如果指定大小为0则意味着完全禁用多值属性MVA的更新。一旦达到了这个内存池大 小的限制,尝试更新多值属性MVA将得到错误。但普通的(标量的)属性仍然可以更新。由于内部实现上的技术困难,一旦多值属性MVA有所更新,则索引上发 生的任何更新改变都不能在索引重建前被写入(store,flush)磁盘,尽管这可能在未来实现。同时,多值属性MVA是设计用来在索引重建前迅速反应数据库中的变化,而不是一种永久存储的机制。
mva_updates_pool = 16M
崩溃日志文件的路径(正式地说叫做前缀)。可选选项,默认值为空(不创建崩溃日志文件)。于版本0.9.9-rc1引入。
这个选项用于调试,有了它就可以捕捉那些个别的令人不快的造成崩溃的查询,而不比影响正在使用的用于生产的服务器实例。一旦启用了这个选项,searchd
会拦截造成崩溃的信号,例如SIGSEGV,并将那些不愉快的查询包转储到一个叫做“crash_log_path.PID”的文件中,其中PID是崩溃了的进程的ID。
crash_log_path = /home/sphinx/log/crashlog
Maximum allowed per-query filter count. Only used for internal sanity checks, does not directly affect RAM use or performance. Optional, default is 256. Introduced in version 0.9.9-rc1. 每次查询允许设置的过滤器的最大个数。只用于内部检查,不直接影响内存使用或性能。可选选项,默认值是256。于版本0.9.9-rc1引入。
max_filters = 1024
TCP监听积压列表长度。可选选项,默认值是5。
在Windows系统上创建的Sphinx目前(版本0.9.9)只能一个接一个地处理请求。同时发生的请求会被操作系统级别的TCP协议栈装入到 一个队列中,无法如对的请求立即失败并收到“连接被拒”错误信息。listen_backlog选项控制这个连接队列的长度。非Windows平台上创建 的Sphinx使用默认值即可。
listen_backlog = 20
关于中文分词的详细配置实例和分词词典的自定义设置,可以访问Coreseek网站中文分词核心配置查看。
核心配置:charset_dictpath
= /usr/local/mmseg3/etc/charset_type
= zh_cn.utf-8 #charset_table
= .................... #需将原有的该配置注释掉ngram_len
= 0
mmseg分词相关的配置选项,需要保存到文件mmseg.ini
,并将该配置文件放置到charset_dictpath
所设置的目录中。
基本配置: [mmseg]merge_number_and_ascii
=0; ;合并英文和数字 abc123/xnumber_and_ascii_joint
=-; ;定义可以连接英文和数字的字符compress_space
=1; ;暂不支持seperate_number_ascii
=0; ;就是将字母和数字打散 其中,分号表示注释
Python数据源的各种实例程序,可以访问Coreseek网站Python数据源获取。该部分的相关文档,还在继续完善中。
#Python数据源基本演示程序 #/usr/local/coreseek/etc/pysource/csft_demo/__init__.py # -*- coding:utf-8 -*- class MainSource(object): def __init__(self, conf): self.conf = conf self.data = [ {'id':1, 'subject':u"标题1", 'date':1270131607}, {'id':2, 'subject':u'标题2', 'date':1270135548}, ] self.idx = 0 def GetScheme(self): return [ ('id' , {'docid':True, } ), ('subject', { 'type':'text'} ), ('date', {'type':'integer'} ), ] def GetKillList(self): return [3,1] def GetFieldOrder(self): return ('subject') def Connected(self): pass def OnBeforeIndex(self): print 'before index called' pass def NextDocument(self): if self.idx < len(self.data): item = self.data[self.idx] self.id = item['id'] self.subject = item['subject'].encode('utf-8') self.date = item['date'] self.idx += 1 return True else: return False pass def OnAfterIndex(self): print 'after index called' pass def OnIndexFinished(self): print 'after index finished' pass if __name__ == "__main__": source = MainSource() source.Connected() source.OnBeforeIndex() while source.NextDocument(): print "id=%d, title=%s" % (source.docid, source.title) source.OnAfterIndex() source.OnIndexFinished() pass #eof
返回所有需要被索引的字段的属性
def GetScheme(self): return [ ('id' , {'docid':True, } ), ('subject', { 'type':'text'} ), ('date', {'type':'integer'} ), ]
在检索字段设置中,必须且仅有一个字段需要设置为docid,对应于SQL数据源中的文档编号。其他字段的属性,可以为integer,对应于sql_attr_uint
,或者text,对应于全文检索字段。
获取实际的需要参与检索的数据,按条获取,需要获取的字段,作为self自身的属性给出,相当于sql_query
的作用,每次读取一条数据
def NextDocument(self): if self.idx < len(self.data): item = self.data[self.idx] self.id = item['id'] self.subject = item['subject'].encode('utf-8') self.date = item['date'] self.idx += 1 return True else: return False pass
sql_str2ordinal_column
max_prefix_len
, max_infix_len
)@*
syntax to reset current field to query languagedocinfo=none
casemmap()
limits for attributes and wordlists (now able to map over 4 GB on x64 and over 2 GB on x32 where possible)malloc()
pressure in head daemon (search time should not degrade with time any more)test.php
command line options.spl
files getting unlinkedpgsql
source typemmap()ing
for attributes and wordlist (improves search time, speeds up fork()
greatly)-g
, removed -fomit-frame-pointer
)unlink()ed
on bind()
failure--with-mysql-includes/libs
(they conflicted with well-known paths)max_matches
per-query--with-debug
option to configure to compile in debug mode-DNDEBUG
when compiling in default modemin_word_len
) words prepended to next fieldconfigure
scriptmin_word_len
option to indexmax_matches
option to searchd, removed hardcoded MAX_MATCHES limitexample.sql
--stdin
command-line option to search utility--noprogress
option to indexer--index
option to searchtime(NULL)
calls in time-segments mode