Sphinx参考手册(四)

转载自http://sphinxsearch.com/wiki/doku.php?id=sphinx_manual_chinese ,虽然版本较旧但大部分功能和配置说明目前的新版本还是适用。英文水平好的最好查看最新版的英文手册。

4. 搜索

4.1. 匹配模式

有如下可选的匹配模式:

  • SPH_MATCH_ALL, 匹配所有查询词(默认模式);
  • SPH_MATCH_ANY, 匹配查询词中的任意一个;
  • SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配;
  • SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式 (参见  Section 4.2, “布尔查询语法”);
  • SPH_MATCH_EXTENDED, 将查询看作一个Sphinx/Coreseek内部查询语言的表达式 (参见  Section 4.3, “扩展查询语法”). 从版本Coreseek 3/Sphinx 0.9.9开始, 这个选项被选项SPH_MATCH_EXTENDED2代替,它提供了更多功能和更佳的性能。保留这个选项是为了与遗留的旧代码兼容——这样即使Sphinx及其组件包括API升级的时候,旧的应用程序代码还能够继续工作。
  • SPH_MATCH_EXTENDED2, 使用第二版的“扩展匹配模式”对查询进行匹配.
  • SPH_MATCH_FULLSCAN, 强制使用下文所述的“完整扫描”模式来对查询进行匹配。注意,在此模式下,所有的查询词都被忽略,尽管过滤器、过滤器范围以及分组仍然起作用,但任何文本匹配都不会发生.

当如下条件满足时,SPH_MATCH_FULLSCAN模式自动代替其他指定的模式被激活:

  1. 1. 查询串是空的(即长度字符串为零)
  2. docinfo 存储方式为  extern.

在完整扫描模式中,全部已索引的文档都被看作是匹配的。这类匹配仍然会被过滤、排序或分组,但是并不会做任何真正的全文检索。这种模式可以用来统一全文检索和非全文检索的代码,或者减轻SQL服务器的负担(有些时候Sphinx扫描的速度要优于类似的MySQL查询)。 “在论坛中搜索帖子”这件事可用作完整搜索模式的例子:用SetFilter()指定用户ID但不提供任何查询词,Sphinx会匹配SetFilter()所能匹配的全部文档,也就是这个用户ID对应的全部帖子。默认情况下,其结果的第一排序标准是相关度,其次是Sphinx文档ID,正序(较老的文档在前)。

注意,在完整扫描模式中,文档必须有至少一个属性。否则,即便设置docinfo的存储方式为extern,也无法启用完整扫描模式。

4.2. 布尔查询语法

布尔查询允许使用下列特殊操作符:

  • 显式的与(AND)操作符:
    hello & world
  • 或(OR)操作符:
    hello | world
  • 非(NOT)操作符:
    hello -world
    hello !world
  • 分组(grouping):
    ( hello world )

以下是一个使用了如上全部操作符的例子:

Example 5. 布尔查询示例

( cat -dog ) | ( cat -mouse)


与(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个文档),对这种执行查询可能需要很长的时间。

4.3. 扩展查询语法

在扩展查询模式中可以使用如下特殊操作符:

  •  或(OR)操作符:
    hello | world
  •  非(NOT)操作符:
    hello -world
    hello !world
  •  字段(field)搜索符:
    @title hello @body world
  •  字段限位修饰符(版本Coreseek 3/Sphinx 0.9.9-rc1中引入):
    @body[50] hello
  •  多字段搜索符:
    @(title,body) hello world
  •  全字段搜索符:
    @* hello
  •  词组搜索符:
    "hello world"
  •  近似搜索符:
    "hello world"~10
  •  阀值匹配符:
    "the world is a wonderful place"/3
  •  严格有序搜索符(即“在前”搜索符):
    aaa << bbb << ccc
  •  严格形式修饰符(版本Coreseek 3/Sphinx 0.9.9-rc1中引入):
    raining =cats and =dogs
  •  字段开始和字段结束修饰符 (版本Coreseek 3.1/Sphinx 0.9.9-rc2中引入):
    ^hello world$

以下是上述某些操作符的示例:

Example 6. 扩展查询示例

"hello world" @title "example program"~5 @body python -(php|perl) @* code


例子中查询的完整解释如下:

  • • 在文档的任意字段中找相邻的“hello”和“world”
  • • 不仅如此,符合上述条件的文档的title字段中还必须包含 “example”和“program”这两个词,并且他们之间至多有10个(不包括10个)其他的词(例如“example PHP program”可以匹配,但“example script to introduce outside data into the correct context for your program”就不行,因为中间有10个或以上的词。
  • • 同时,body字段必须含有词“python”,但既没有“php”也没有“perl”
  • 最后, 任一字段中包含”code“.

与(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

4.4. 权值计算

采用何种权值计算函数(目前)取决于查询的模式。

权值计算函数进行如下两部分主要部分:

  1. 词组评分,
  2. 统计学评分.

词组评分根据文档和查询的最长公共子串(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)明显更高的搜索质量。

4.5. 排序模式

可使用如下模式对搜索结果排序:

  • SPH_SORT_RELEVANCE 模式, 按相关度降序排列(最好的匹配排在最前面)
  • SPH_SORT_ATTR_DESC 模式, 按属性降序排列 (属性值越大的越是排在前面)
  • SPH_SORT_ATTR_ASC 模式, 按属性升序排列(属性值越小的越是排在前面)
  • SPH_SORT_TIME_SEGMENTS 模式, 先按时间段(最近一小时/天/周/月)降序,再按相关度降序
  • SPH_SORT_EXTENDED 模式, 按一种类似SQL的方式将列组合起来,升序或降序排列。
  • SPH_SORT_EXPR 模式,按某个算术表达式排序。

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 模式

在SPH_SORT_TIME_SEGMENTS模式中,属性值被分割成“时间段”,然后先按时间段排序,再按相关度排序。

时间段是根据搜索发生时的当前时间戳计算的,因此结果随时间而变化。所说的时间段有如下这些值:

  • 最近一小时
  • 最近一天
  • 最近一周
  • 最近一月
  • 最近三月
  • 其他.

时间段的分法固化在搜索程序中了,但如果需要,也可以比较容易地改变(需要修改源码)。

这种模式是为了方便对Blog日志和新闻提要等的搜索而增加的。使用这个模式时,处于更近时间段的记录会排在前面,但是在同一时间段中的记录又根据相关度排序-这不同于单纯按时间戳排序而不考虑相关度。

SPH_SORT_EXTENDED 模式

在 SPH_SORT_EXTENDED 模式中,您可以指定一个类似SQL的排序表达式,但涉及的属性(包括内部属性)不能超过5个,例如:

@relevance DESC, price ASC, @id DESC

只要做了相关设置,不管是内部属性(引擎动态计算出来的那些属性)还是用户定义的属性就都可以使用。内部属性的名字必须用特殊符号@开头,用户属性按原样使用就行了。在上面的例子里,@relevance@id是内部属性,而price是用户定义属性。

已知的内置属性:

  • @id (匹配文档的 ID)
  • @weight (匹配权值)
  • @rank (等同 weight)
  • @relevance (等同 weight)
  • @random (随机顺序返回结果)

@rank 和 @relevance 只是 @weight 的别名.

SPH_SORT_EXPR 模式

表达式排序模式使您可以对匹配项按任何算术表达式排序,表达式中的项可以是属性值,内部属性(@id和@weight),算术运算符和一些内建的函数。例如:

$cl->SetSortMode ( SPH_SORT_EXPR,
        "@weight + ( user_karma + ln(pageviews) )*0.1" );

支持的运算符和函数如下。它们是模仿MySQL设计的。函数接受参数,参数的数目根据具体函数的不同而不同。

  • 运算符: +, -, *, /, <, > ⇐, >=, =, <>.
  • 布尔操作符: AND, OR, NOT.
  • 无参函数: NOW().
  • 一元函数(一个参数): ABS(), CEIL(), FLOOR(), SIN(), COS(), LN(), LOG2(), LOG10(), EXP(), SQRT(), BIGINT().
  • 二元函数(两个参数): MIN(), MAX(), POW(), IDIV().
  • 其他函数: IF(), INTERVAL(), IN(), GEODIST().

计算可以以三种不同的精度进行:(a) 单精度32位IEEE754浮点值(默认情况),(b) 32位有符号整数,© 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),它根据坐标计算两个指定点之间的地表距离。请注意经纬度都要以角度为单位,而结果是以米为单位的。四个参数都可以是任意表达式。当其中一对参数引用的是文档属性对而另一对参数是常数,系统会自动选择一条优化的路径。

4.6. 结果分组(聚类)

有时将搜索结果分组(或者说“聚类”)并对每组中的结果计数是很有用的-例如画个漂亮的图来展示每个月有多少的blog日志,或者把Web搜索结果按站点分组,或者把找到的论坛帖子按其作者分组。

理论上,这可以分两步实现:首先在Sphinx中做全文检索,再在SQL服务器端对得到的ID分组。但是现实中在大结果集(10K到10M个匹配)上这样做通常会严重影响性能。

为避免上述问题,Sphinx提供了一种“分组模式”,可以用API调用SetGroupBy()来开启。在分组时,根据group-by值给匹配项赋以一个分组。这个值用下列内建函数之一根据特定的属性值计算:

  • SPH_GROUPBY_DAY, 从时间戳中按YYYYMMDD格式抽取年、月、日;
  • SPH_GROUPBY_WEEK, 从时间戳中按YYYYNNN格式抽取年份和指定周数(自年初计起)的第一天;
  • SPH_GROUPBY_MONTH, 从时间戳中按YYYYMM格式抽取月份;
  • SPH_GROUPBY_YEAR, 从时间戳中按YYYY格式抽取年份;
  • SPH_GROUPBY_ATTR, 使用属性值自身进行分组.

最终的搜索结果中每组包含一个最佳匹配。分组函数值和每组的匹配数目分别以“虚拟”属性 @group 和 @count 的形式返回.

结果集按group-by排序子句排序,语法与SPH_SORT_EXTENDED 排序子句的语法相似。除了@id@weight,分组排序子句还包括:

  • @group (groupby函数值),
  • @count (组中的匹配数目).

默认模式是根据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())

4.7. 分布式搜索

为提高可伸缩性,Sphnix提供了分布式检索能力。分布式检索可以改善查询延迟问题(即缩短查询时间)和提高多服务器、多CPU或多核环境下的吞吐率(即每秒可以完成的查询数)。这对于大量数据(即十亿级的记录数和TB级的文本量)上的搜索应用来说是很关键的。

其关键思想是对数据进行水平分区(HP,Horizontally partition),然后并行处理。

分区不能自动完成,您需要

  • 在不同服务器上设置Sphinx程序集( indexersearchd)的多个实例;
  • 让这些实例对数据的不同部分做索引(并检索);
  • searchd的一些实例上配置一个特殊的分布式索引;
  • 然后对这个索引进行查询.

这个特殊索引只包括对其他本地或远程索引的引用,因此不能对它执行重新建立索引的操作,相反,如果要对这个特殊索引进行重建,要重建的是那些被这个索引被引用到的索引。

searchd收到一个对分布式索引的查询时,它做如下操作

  1. 连接到远程代理;
  2. 执行查询;
  3. (在远程代理执行搜索的同时)对本地索引进行查询;
  4. 接收来自远程代理的搜索结果;
  5. 将所有结果合并,删除重复项;
  6. 将合并后的结果返回给客户端.

在应用程序看来,普通索引和分布式索引完全没有区别。 也就是说,分布式索引对应用程序而言是完全透明的,实际上也无需知道查询使用的索引是分布式的还是本地的。 (就算是在0.9.9之中, Sphinx也不支持以其他的方式来结合分布式索引进行搜索, 也许在将来会去掉该限制.)

任一个searchd实例可以同时做为主控端(master,对搜索结果做聚合)和从属端(只做本地搜索)。这有如下几点好处:

  1. 集群中的每台机器都可以做为主控端来搜索整个集群,搜索请求可以在主控端之间获得负载平衡,相当于实现了一种HA(high availability,高可用性),可以应对某个节点失效的情况。
  2. 如果在单台多CPU或多核机器上使用,一个做为代理对本机进行搜索的searchd实例就可以利用到全部的CPU或者核。

如果在单台多CPU或多核机器上使用,一个做为代理对本机进行搜索的searchd实例就可以利用到全部的CPU或者核。

4.8.  searchd查询日志格式

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)可以是如下值之一

  • “all” 代表 SPH_MATCH_ALL 模式;
  • “any” 代表 SPH_MATCH_ANY 模式;
  • “phr” 代表 SPH_MATCH_PHRASE 模式;
  • “bool” 代表 SPH_MATCH_BOOLEAN 模式;
  • “ext” 代表 SPH_MATCH_EXTENDED 模式;
  • “ext2” 代表 SPH_MATCH_EXTENDED2 模式;
  • “scan” 代表使用了完整扫描模式,这可能是由于设置了SPH_MATCH_FULLSCAN模式导致的,也可能是因为查询是空的。 (参见文档  匹配模式)

排序模式(sort-mode)可以取如下值之一:

  • “rel” 代表 SPH_SORT_RELEVANCE 模式;
  • “attr-” 代表 SPH_SORT_ATTR_DESC 模式;
  • “attr+” 代表 SPH_SORT_ATTR_ASC 模式;
  • “tsegs” 代表 SPH_SORT_TIME_SEGMENTS 模式;
  • “ext” 代表 SPH_SORT_EXTENDED 模式.

此外,如果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时间)

4.9. MySQL 协议支持与 SphinxQL

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
  • SHOW WARNINGS
  • SHOW STATUS
  • SHOW META

SELECT 语句,语法仿照标准SQL,但有一些Sphinx特有的扩展,也缺少一些标准SQL的特性(比如(目前)不支持JOIN)。具体地说:

  • 列列表子句。列名、任意表达式以及星号(“*”)都允许出现在列列表中(即“SELECT @id, group_id*123+456 FROM test1”是合法的)。与标准SQL不同,任何计算出的表达式都必须有一个有效的标识符作为别名。目前,特殊名称必须有一个前导的“at”符号(@),例如@id和@weight。这个限制未来会被放宽。.
  • • FROM子句。FROM子句列举了要从哪些索引中进行搜索。与标准SQL不同,逗号的意思类似它在 Query()API调用中的意思,代表全文索引的枚举,而不代表JOIN。
  • • WHERE子句。这个子句的内容既可以对应到全文查询,也可以对应过滤器。比较操作符(=, !=, <, >, ⇐, > =)、IN()、AND、NOT和BETWEEN等都被支持,她们直接映射成过滤器。而OR操作符尚未得到支持,但未来会支持。支持MATCH(‘query’)这种形式,它被映射成一个全文查询。系统按照 全文查询规则理解查询。在WHERE子句中最多只能有一个MATCH()。
  • • GROUP BY子句。目前仅支持根据一个列进行分组, 但这个列可以是一个计算出来的表达式。
    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
  • WITHIN GROUP ORDER BY子句。这个子句是Sphinx引入的,它使我们可以控制一个分组中最优的行是怎样选出的。这个自己的语法跟标准的ORDER BY子句相同:
    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
  • ORDER BY子句。不同于标准SQL,只能根据列名(而不是表达式)排序,必须显式地写明ASC(升序)或者DESC(降序)。不过列名可以是通过表达式计算出来的。
    SELECT *, @weight*10+docboost AS skey FROM example ORDER BY skey
  • LIMIT子句。支持LIMIT N和LIMIT M,N两种格式。与标准SQL不同(但是就像在Sphinx API中那样),默认有个隐含的LIMIT 0,20。
  • • OPTION子句。这是Sphinx引入的特殊扩展,它使我们可以设置一些只影响一个查询的选项。语法如下:
    OPTION <optionname>=<value> [ , ... ]

    支持设置的选项和允许设置的值如下: 'ranker' - 以下值之一 'proximity_bm25', 'bm25', 'none', 'wordcount', 'proximity', 'matchany', 或者 'fieldmask' 'max_matches' - 整数(当前查询的最大匹配数目) 'cutoff' - 整数(最大匹配数阈值) 'max_query_time' - 整数(最大搜索时间阈值,毫秒) 'retry_count' - 整数(分布式重试数目) 'retry_delay' - 整数(分布式重试的延迟时间,毫秒) 例子:

    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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值