[coreseek/sphinx学习笔记4]--搜索

[参考Coreseek 全文检索服务器 2.0 (Sphinx 0.9.8)参考手册,详情见 http://www.coreseek.cn/docs/sphinx_doc_zhcn_0.9.pdf  

4.1 匹配模式
有如下可选的匹配模式:
    SPH_MATCH_ALL, 匹配所有查询词(默认模式)
    SPH_MATCH_ANY, 匹配查询词中的任意一个
    SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配
    SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式
    SPH_MATCH_EXTENDED, 将查询看作一个 Sphinx 内部查询语言的表达式
还有一个特殊的“完整扫描”模式,当如下条件满足时,该模式被自动激活:
    查询串是空的(即长度为零)
    docinfo存储方式为 extern

4.2 权重计算
采用何种权值计算函数(目前)取决于查询的模式。
There are these major parts which are used in the weighting functions:
权值计算函数进行如下两部分主要部分: 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.3 排序模式
可使用如下模式对搜索结果排序:
    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 (match ID)
    @weight (match weight)
    @rank (match weight)
    @relevance (match weight)
    @id(匹配的 ID)
    @weight(匹配权值)
    @rank(匹配权值)
    @relevance(匹配权值)
    @rank 和@relevance 只是@weight 的额外别名。

SPH_SORT_EXPR 模式
    表达式排序模式使您可以对匹配项按任何算术表达式排序,表达式中的项可以是属性值,内部属性(@id 和@weight),算术运算符和一些内建的函数。例如:
    $cl->SetSortMode ( SPH_SORT_EXPR,"@weight + ( user_karma + ln(pageviews) )*0.1" );
    支持的运算符和函数如下。它们是模仿 MySQL 设计的。函数接受参数,参数的数目根据具体函数的不同而不同。
    Operators: +, -, *, /, <, > <=, >=, =, <>.
    Unary (1-argument) functions: abs(), ceil(), floor(), sin(), cos(), ln(), log2(), log10(), exp(),sqrt().
    Binary (2-argument) functions: min(), max(), pow().
    Ternary (3-argument) functions: if().
运算符: +, -, *, /, <, > <=, >=, =, <>.
一元函数(一个参数):abs(), ceil(), floor(), sin(), cos(), ln(), log2(), log10(), exp(),sqrt().
二元函数(两个参数):min(), max(), pow().
三元函数(三个参数):if().
    全部的计算都以单精度 32 位 IEEE754 浮点数进行。比较操作符(比如=和<=)在条件为真时返回 1.0,否则返回 0.0。例如(a=b)+3 在属性“a”与属性“b”相等时返回 4,否则返回3。与 MySQL 不同,相等性比较符(即=和<>)中引入了一个小的阈值(默认是 1e-6)。
    如果被比较的两个值的差异在阈值之内,则二者被认为相等。
    全部的一元和二元函数的意义都很明确,他们的行为跟在数学中的定义一样。但 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’做为结果。

4.4 结果分组(聚类)
    有时将搜索结果分组(或者说“聚类”)并对每组中的结果计数是很有用的-例如把找到的论坛帖子按其作者分组。
    理论上,这可以分两步实现:首先在 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”分组,那么:
    结果中包含每天的匹配结果中最相关的那一个,如果那天有记录匹配的话。
    结果中还附加给出天的编号和每天的匹配数目
    结果以天的编号降序排列(即最近的日子在前面)

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

    其关键思想是将待搜索数据做水平分区(HP,Horizontally partition),然后并行处理。
分区不能自动完成,您需要:
    在不同服务器上设置 Sphinx 程序集(indexer 和 searchd)的多个实例
    让这些实例对数据的不同部分做索引(并检索)
    在 searchd 的一些实例上配置一个特殊的分布式索引
    然后对这个索引进行查询
    这个特殊索引只包括对其他本地或远程索引的引用,因此不能对它执行重新建立索引的操作,相反,如果要对这个特殊索引进行重建,要重建的是那些被这个索引被引用到的索引。
    当 searchd 收到一个对分布式索引的查询时,它做如下操作:
    1. 连接到远程代理
    2. 执行查询
    3. (在远程代理执行搜索的同时)对本地索引进行查询
    4. 接收来自远程代理的搜索结果
    5. 将所有结果合并,删除重复项
    6. 将合并后的结果返回给客户端
    在应用程序看来,普通索引和分布式索引完全没有区别。
    任一个 searchd 实例可以同时做为主控端(master,对搜索结果做聚合)和从属端(只做本地搜索)。这有如下几点好处:
    1. 集群中的每台机器都可以做为主控端来搜索整个集群,搜索请求可以在主控端之间获得负载平衡,相当于实现了一种 HA(high availability,高可用性),可以应对某个节点失效的情况。
    2. 如果在单台多 CPU 或多核机器上使用,一个做为代理对本机进行搜索的 searchd 实例就可以利用到全部的 CPU 或者核。
    更好的 HA 支持已在计划之中,到时将允许指定哪些代理之间互相备份、有效性检查、跟踪运行中的代理、对检索请求进行负载均衡,等等。

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

排序模式(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 模式.

你可能感兴趣的:(PHP,搜索,sphinx,coreseek)