`
wbj0110
  • 浏览: 1586928 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Lucene打分规则

阅读更多
搜索排序结果的控制
      Lucnen作为搜索引擎中,应用最为广泛和成功的开源框架,它对搜索结果的排序,有一套十分完整的机制来控制;但我们控制搜索结果排序的目的永远只有一个,那就是信息过滤,让用户快速,准确的找到其想要的结果,丰富用户体验。
 
以前看过一个牛人的博客,总结了4个地方,可对Lucene检索结果的排序进行控制,现在已经记不住。我自己简单整理了下面几个,若有疏漏,欢迎补充:
 
1.    通过Lucene自有的查询表达式:Lucene提供相当丰富的表达式解析,要细讲就多了去了;这里只强调下,我在项目中用的比较多的是通过对指定域的加权,来影响检索结果(例如:field1:(XXX)^10 or field2:(XXX)^5;其中XXX是用户提交的检索)
 
2.    权重的控制:这是在建索引的时候就写入索引的,查询时只是读取出来,用乘的方式来对一些检索结果加分。据我自己看Lucene代码,Similarity中也能在建索引时,对权重的写入进行控制;后面会细讲。
 
3.    Controller 模块:Lucene的排序流程控制模块,里面提供的一些接口能让你对打分后的搜索结果进行一些筛选和调整。
 
 4.    Similarity 模块:Lucene的搜索结果打分控制模块,也是这里要详细分析的模块。他能让你对一个检索结果的打分进行优化,或面目全非,哈哈。
 
 
 
Lucene的打分公式
        要理解Similarity模块对打分结果控制,首先要了解Lucene自己评分原理:相似度评分公式;此公式是目前公认的用户体验较好的一个,原理是根据余弦定理。下面是在摘自《Lucene实战》(第二版)的公式表达式:
 

 
其中q 为查询语句,t 是q 分词后的每一项, d为去匹配的文档。
 
      接下来对公式中的每一个函数,进行详解,他们都能在 Similarity 模块中进行控制。
 
 
 
Lucene打分流程
        首先,我简单说明下,Lucene对一次查询是如何封装;这涉及到对打分公式是如何调用的,如此一来更能全面的了解打分流程:
 
         第一步的处理肯定是分词,查询语句 => term_1, term_2 …  term_n(n∈[1,∞]),紧接着是将这些term 封装成Query对象,总的Query对象是BooleanQuery,它里面包含和分词数相同TermQuery,和分词后的词项一一对应;这是对一个域的查询,若你多个域联合查询,那就会有多个这样的BooleanQuery,被一个更大的BooleanQuery包裹着。
 
         而打分公式,贯穿所有Query,其中一部分在TermQuery中计算,一部分在BooleanQuery计算,最后按此计算出的得分进行排序,就得到了我们的搜索结果。
 
         下面是我通过explain(Query query, int doc) 导出的打分解释:
 

 
        对照Lucene的打分解释,我们一层一层往里拨(上述每个缩进为一层),每一个函数都能在Similarity中进行控制。
 
1.      首先第一层:3.3936599 = (MATCH) product of:,是此条记录的总得分。
 
2.      第二层:8.48414992 = (MATCH) sum of: 它对应一个BooleanQuery,它把它包含的TermQuery的得分累加起来,由于TermQuery总共有5个,此条结果中只匹配了2个,所以最后一行将得分乘以了0.4得到最后的打分,coord()在Similarity中的默认实现如下:
 
/** Implemented as <code>overlap / maxOverlap</code>. */
@Override
public float coord(int overlap, int maxOverlap) {
  return overlap / (float)maxOverlap;
}
你也可以继承Similarity对此方法重写。
 
3.      第三层:(MATCH) weight(field:XXX in m), product of: 有2个,它们分别是“三国”、“无双”对应的词项查询TermQuery的得分。
 
        再往里,就是TermQuery的打分规则了,里面的函数已经和公式有所对应了,下面就详细介绍TermQuery中每一项计算的作用。
 
Similarity 函数详解
 
    TermQuery中有4个函数,都是Similarity里可以控制的函数,他们分别是queryNorm、tf、idf、fieldNorm
 
queryNorm:
对于某一次搜索中结果的排序没有影响,在一次搜索中queryNorm的值是固定的。这里就不介绍了
 
tf(t in q)
         此函数表示词项T 在该文档中的该字段里 出现的频率;对应到上图的例子中:既是分词后的词项(三国或 无双)在此条记录中Name字段里出现的频率。当然出现的次数越多,它返回的值越大,也正好反映了此文档的重要性。下面是DefaultSimilarity 中的默认实现的默认实现。    
 
/** Implemented as <code>sqrt(freq)</code>. */
@Override
public float tf(float freq) {
  return (float)Math.sqrt(freq);
}
 
         默认实现是开平方。同样你可以重写此函数。
 
         它实际对结果排序的影响,表现和它的意义一样,一个搜索结果包含的搜索关键词越多,得分越高。
 
idf(t)
         此函数出现了两次,也刚好对应公式中的 idf(t)^2;
 
         这个函数被称作倒频率,表示词项T 在所有文档中出现的频率。若它在所有文档中出现的次数越多,表明这个词项T 越不重要;以下是DefaultSimilarity的默认实现。
 
/** Implemented as <code>log(numDocs/(docFreq+1)) + 1</code>. */
@Override
public float idf(int docFreq, int numDocs) {
  return (float)(Math.log(numDocs/(double)(docFreq+1)) + 1.0);
}
 
         此函数实际对结果排序的影响,在于当一次搜索包含多个词项时,文档A和B分别包含了其中一个词项;比如A包含“三国”,B包含“无双”;那么“三国”和“无双”的倒频率就会影响,让A、B的得分产生差异了。若词项只有一个,那本次搜索idf(t) 实际对结果排序不会产生影响。
 
 
 
fieldNorm (t)
3.0以后:computeNorm(String field, FieldInvertState state)
         它的值对应着公式中 boost(t.field in d)×lengthNorm(t.field in d) 的值。其中boost(t.field in d)的值,在创建索引时就被记录下来,而lengthNorm(t.field in d)得值,会在查询过程中计算;它表示此条搜索结果中,给定字段中包含词项的总数;若值越大,得分越低;你可以这么理解;若A文档有包含了1000个词项,关键词出现的频率为10;而B文档包20个词项,相同关键词出现的频率为8;很明显B文档的打分应该要高一些;由此函数可以起到这样的效果。以下是Similarity 的默认实现,函数名在3.0以后变了,原来就叫lengthNorm
 
/** Decodes a normalization factor stored in an index.
 * <p>
 * <b>WARNING: If you override this method, you should change the default
 *    Similarity to your implementation with {<a href="http://my.oschina.net/link1212" target="_blank" rel="nofollow">@link</a> Similarity#setDefault(Similarity)}.
 *    Otherwise, your method may not always be called, especially if you omit norms
 *    for some fields.</b>
 * <a href="http://my.oschina.net/u/244147" target="_blank" rel="nofollow">@see</a> #encodeNormValue(float)
 */
 
public float decodeNormValue(byte b) {
  return NORM_TABLE[b & 0xFF];  // & 0xFF maps negative bytes to positive above 127
}
    至此Lucene打分流程和Similarity模块的函数已经将的差不多了。可以通过这些函数让你的搜索展示出完全不一样的效果,这也需要根据不同的业务慢慢调试,才能得出最优化的搜索结果 。
分享到:
评论

相关推荐

    lucene 自定义评分

    这样,Lucene 就会使用我们的自定义评分规则进行匹配和排序。 在实际应用中,可能还需要考虑其他因素,如用户偏好、文档质量、关键词位置等。这些都可以通过自定义相似度类中的方法来实现。例如,对于位置敏感的...

    Lucene3.5源码jar包

    2. **分词器(Tokenizer)与过滤器(Filter)**:Lucene支持自定义的分词规则,如`StandardTokenizer`和`LowerCaseFilter`。这些在`analysis`包下的源码中可以找到,它们负责将原始文本转换为可搜索的术语。 3. **...

    lucene 2.0 api以及lucene 3.0 api

    3. **搜索执行**: 使用 `Searcher` 类进行搜索操作,`Hits` 类表示搜索结果,其中包含匹配的文档及其评分。 4. **分析器(Analyzer)**: Lucene 2.0 提供了多种预定义的分析器,如 `StandardAnalyzer`,处理文本分词...

    lucene3源码分析

    - **相关性评分**:为了提供最相关的搜索结果,系统需要计算查询与文档的相关度。 ##### 2. 索引里面究竟存些什么? 索引是全文检索系统的核心组成部分,用于存储文档的关键信息以便快速访问。这些信息主要包括: ...

    Lucene3.3.0学习Demo

    6. **结果排序**:Lucene根据评分对搜索结果进行排序,返回给用户。可以自定义评分函数以适应不同的排序策略。 在这个"Lucene3.3.0学习Demo"中,你可以期待以下内容: - 示例代码展示如何初始化索引目录,创建`...

    luncene 4.6 自定义查询评分规则

    在本篇文章中,我们将深入探讨如何在Lucene 4.6中实现自定义查询评分规则。此技术允许用户根据特定需求调整文档的相关性评分,从而更精确地满足搜索需求。 ### Lucene 4.6 自定义查询评分规则 #### 一、背景与概述...

    Lucene实战(中文版第二版)对应Lucene版本

    10. **扩展性**:Lucene的API设计使得开发者可以轻松地扩展其功能,如自定义分词器、查询解析器和评分模型等。 通过《Lucene实战(中文版第二版)》结合Lucene 3.0.3源代码,读者不仅可以掌握Lucene的基本用法,还...

    全文检索引擎Lucene

    4. **排序和显示结果(Sorting and Displaying)**: 搜索结果按照评分排序,默认是降序,用户可以自定义排序规则。仅显示高分文档的部分内容,如标题和摘要。 **三、Lucene的扩展和应用** 1. **Solr和Elastic...

    lucene实例

    在实际应用中,你可能还需要考虑其他方面,如优化搜索性能、处理中文分词、实现缓存策略、设置评分规则等。例如,对于中文,可以使用IK Analyzer或其他专门的中文分词库。而为了提升效率,可以使用NRT(Near Real ...

    lucene.net 2.9.1 源码

    1. 定制Analyzer:根据特定语言或业务需求,编写自定义的分词规则。 2. 索引优化:调整索引策略,如批量索引、实时索引,以及选择合适的Directory实现。 3. 查询扩展:实现复杂查询逻辑,如布尔查询、短语查询、近似...

    Lucene2.4.1

    - `Hit`:搜索结果中的一个匹配项,包含了文档的评分和相关信息。 2. demos包:包含了Lucene的示例程序,帮助开发者快速理解和上手使用。这些示例展示了如何创建索引、执行查询以及处理结果。例如: - `...

    Lucene-2.0学习文档

    结合以上文件,我们可以看到Lucene-2.0的学习不仅需要理解基本的索引构建和搜索原理,还需要掌握如何自定义排序规则和分析器以满足特定需求。此外,通过阅读和分析这些源码,开发者还可以深入理解Lucene的内部工作...

    lucene2.0.0

    7. **Analyzer**:可以自定义实现,控制分词规则。 四、实战应用 在实际项目中,你可以根据需求创建自定义的Analyzer来适应特定的语言环境,例如中文分词。通过IndexWriter添加和更新Document,构建索引。利用...

    Lucene.Net.dll

    同时,通过评分机制,Lucene.Net可以对搜索结果进行排序,使最相关的文档优先展示。 除此之外,Lucene.Net.dll还包含了高效的更新和删除策略。当需要更新已索引的文档或者删除不再需要的记录时,Lucene.Net提供了一...

    基于lucene的开发JavaEE项目

    Lucene提供了Analyzer类用于文本分析,可以自定义分词规则以适应不同的语言环境。 3. **索引优化**:为了提高查询性能,我们还需要关注索引的优化,如使用多线程并行索引、设置合理的字段类型、利用位图过滤器...

    lucene-4.6.0全套jar包

    Lucene 4.6.0提供多种预定义的分词器,如标准分词器、中文分词器等,同时也支持自定义分词规则。 4. 索引(Index):索引是Lucene的核心,它将文档内容转化为倒排索引结构,便于快速查找匹配的文档。在4.6.0版本中...

    lucene-2.3.0-src

    Lucene的核心功能包括文档索引、查询解析、评分和结果排序。在2.3.0版本中,这些功能得到了进一步增强,提升了性能和稳定性。源码分析是理解Lucene工作原理的关键,通过阅读源码,我们可以了解其内部数据结构、算法...

    lucene 代码

    - `Analyzer`: 定义了文本分析的规则,如分词器的选择和词形还原等。 - `IndexReader`: 提供访问索引的方法,用于读取索引信息。 - `IndexSearcher`: 执行查询并返回匹配的文档。 - `Document`: 代表一个待索引...

    lucene-4.10.3源码

    3. 搜索:`src/core/org/apache/lucene/search`目录下的代码实现了搜索算法,包括评分、排序和结果集的处理。其中,`IndexSearcher`是主要的搜索接口,它与`Weight`和`Scorer`协同工作,执行实际的搜索任务。 4. ...

    Lucene全文检索案例

    默认情况下,Lucene基于TF-IDF算法计算评分,高分表示文档与查询的相关性更高。你可以根据需求定制排序规则。然后,通过`ScoreDoc`对象获取匹配文档的详细信息,如文档ID,再使用`Document`对象的`get()`方法获取...

Global site tag (gtag.js) - Google Analytics