- 浏览: 277724 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (161)
- 【**计划】 (2)
- 【**Core Java**】 (30)
- 【**JAVA EE】 (6)
- JDBC (3)
- Hibernate专题系列 (0)
- 【**OS】 (14)
- 【**架构设计/设计模式】 (11)
- 【Hadoop】 (3)
- 【**分布式】 (9)
- 模板 (1)
- C (2)
- 常用工具 (1)
- Oracle (2)
- 【Tips】 (3)
- 【数据库】 (2)
- 玩转Ubuntu (0)
- 【计算机网络/网络编程】 (7)
- 【**Search Engine】 (21)
- 【**专题**】 (6)
- 【**Python】 (10)
- XML (1)
- 【**Open Source Framework】 (1)
- 【高级主题】 (1)
- 【存储】 (3)
- 【笔试面试】 (2)
- 【**数据结构与算法设计】 (20)
- 【其他】 (3)
- 【编程练习】 (2)
- 【待完成】 (12)
- 【工作】 (6)
- 【软件研发】 (4)
- 【**多线程多进程编程】 (5)
- 【Web Service】 (1)
- 【表达式解析/JavaCC系列】 (5)
- 【缓存系统:Memcached】 (1)
- 【Java IO/NIO】 (5)
- 【JVM运行机制及内存管理】 (7)
最新评论
-
107x:
...
python list排序 -
yuzhu223:
...
【Python基础】Python的lambda函数与排序 -
Tonyguxu:
分析查询结果的打分小于11.query=1065800715* ...
lucene打分机制的研究 -
Tonyguxu:
query=139320661963.013709 = (MA ...
lucene打分机制的研究 -
Tonyguxu:
query=10658007150.6772446 = (MA ...
lucene打分机制的研究
提出问题
目前在查询时,会将得分小于1的查询结果过滤掉。
本文将回答如下问题:
lucene的打分机制是什么?得分小于1大于1说明什么问题?能否认为得分小于1的结果是部分匹配查询条件而大于1是完全匹配?
根据查询结果的得分小于1来过滤结果是否合理?会不会产生新的问题?
数字后加上"*"对打分有何影响?
lucene的打分机制简介
Lucene的打分机制结合了 Boolean model 和 Vector Space Model (VSM) 。
It uses the Boolean model to first narrow down the documents that need to be scored based on the use of boolean logic in the Query specification(见附录1)
lucene在查询时会首先基于Boolean Model通过在查询语句中的boolean逻辑(AND,OR,NOT)来缩小待打分的文档结果,此过程涉及倒排表的合并,日志检索应用中已经将BooleanClause的occur设置为MUST,查询时会将众多倒排表取交集 。
VSM模型会对上述返回的结果进行打分。Lucene使用了tf-idf值来计算文档与查询条件的相关性,当然lucene改良了VSM模型的打分。lucene的实际使用的打分公式如下:
关于公式中各因子的分析,参见附录2 lucene 3.4 DefaultSimilarity打分公式
打分的目的是为了排序,排序的目的是为了提高搜索的质量,让用户最想要的结果展示在前面。
测试
测试1
Time : 20120110
Total amount : 2336,6081
Index 文件大小: 2.86G
查询条件 |
Time |
Total hits |
score |
|
|
1.1 |
480,8914 |
0.322 至 0.564 |
DefaultSimilarity |
||
1.2 |
" 恭喜您获得 2 个福分,欢迎关注更多精彩互动 " |
20120110 |
1,3190 |
5.834 至 7.001 |
|
1.3 |
" 恭喜您获得 2 个福分,欢迎关注更多精彩互动 " AND SPTOGW |
1,3190 |
5.838 至 7.005 |
|
|
1.4 |
恭喜您获得 2 个福分,欢迎关注更多精彩互动 |
20120110 |
1 , 3190 |
1.596 至 1.916 |
|
测试2
编号 |
查询条件 |
Time |
Total hits |
score |
|
2.1 |
129 , 7241 |
0.580 至 0.677 |
|
||
2.2 |
AND 106580071517 |
1 , 4268 |
1.283 至 1.796 |
|
|
2.3 |
AND 106580071517 AND 6341914 |
20120315 |
4 |
2.749 |
|
2.4 |
GWTOSP |
511 , 6587 |
0.323 至 0.430 |
|
|
2.5 |
AND 1065800715 |
20120315 |
129,7241 |
0.664 至 0.775 |
|
2.6 |
AND 106580071517 AND GWTOSP |
1 , 4268 |
1.311 至 1.835 |
|
|
2.7 |
1065800715 AND 106580071517 AND GWTOSP |
20120315 |
1 , 4268 |
0.270 至 0.378 |
自定义 similarity (idf=1.0)
|
2.8 |
“ 暂无法接收您刚才发送的短信” |
20120315 |
21,7555 |
3.934 至 5.901 |
|
2.9 |
暂无法接收您刚才发送的短信 |
20120315 |
24 , 9941 |
1.133 至 1.699 |
|
2.10 |
20120315 |
21 , 7555 |
1.125 至 1.687 |
自定义 similarity (idf=1.0) |
|
2.11 |
暂无法接收您刚才发送的短信 |
20120315 |
24 , 9941 |
0.25 至 0.375 |
自定义 similarity (idf=1.0) |
2.12 |
“ 暂无法接收您刚才发送的短信” AND 1065800711 |
20120315 |
7,3527 |
2.960 至 5.920 |
|
2.13 |
1065800711 |
20120315 |
221 , 9772 |
0.479 至 0.639 |
|
2.14 |
20120315 |
129 , 7241 |
1.0 |
|
|
2.15 |
13932066196 |
2 |
2.511 至 3.013 |
|
|
2.16 |
1065800715 13932066196 |
20120315 |
2 |
2.557 至 3.069 |
|
编号 |
查询条件 |
Time |
Total hits |
score |
3.1 |
20120110 |
480,8914 |
0.322 至 0.564 |
|
3.2 |
" 恭喜您获得 2 个福分,欢迎关注更多精彩互动 " |
20120110 |
1 , 3190 |
5.834 至 7.001 |
3.3 |
" 恭喜您获得 2 个福分,欢迎关注更多精彩互动 " OR SPTOGW |
20120110 |
480,8914 |
0.005 至 7.005 |
3.4 |
恭喜您获得 2 个福分,欢迎关注更多精彩互动 |
20120110 |
15 , 3826 |
0.024 至 1.916 |
3.5 |
20120315 |
129 , 7241 |
0.580 至 0.677 |
|
3.6 |
1065800715* |
20120315 |
0.58049536 |
1.0 |
3.7 |
13932066196 |
20120315 |
2 |
2.511 至 3.013 |
3.8 |
OR 13932066196 |
129 , 7241 |
0.054 至 3.069 |
|
3.9 |
“ 暂无法接收您刚才发送的短信” OR 1065800711 |
|
236 , 3800 |
1.960 至 5.920 |
3.10 |
暂无法接收您刚才发送的短信 OR 1065800711 |
|
262 , 3001 |
0.818 至 1.766 |
测试结果分析
Q:得分小于1大于1说明什么问题?能否认为得分小于1的结果是部分匹配查询条件而大于1是完全匹配?
A:lucene打分机制中并没有将分数为1作为区别查询结果匹配程度的临界值。分数是>0的任意的数。某个文档的分数越高,说明该文档与该查询的相关性越好,越是用户期望得到的结果。打分通常为了在一次查询中对返回结果排序用的,通过打分lucene会将打分高的结果排在前面分数低的排在后面。
用一个示例解释下什么是相关性,例如有两篇文章都包含lucene这个词,第一篇文章共有10个词,lucene出现了5次,第二篇文章共有1000个词,lucene也出现了5次,按照默认的相关性考虑的话,第一篇文章相关性比第二篇文章要高,在相关性打分上,第一篇文章得到的分数也会比第二篇文章分数高。
>>从测试1.1,2.1,2.5可以看出,使用lucene默认的相关性类similarity,即使是完全匹配的结果的打分也会小于1.
在自定义similarity中,将idf设置为1,这样在计算tf-idf时可以忽略idf,意味着,文档的相关性打分不受含有该term的document的数目的影响。
>>测试2.7说明即使忽略了idf,得分也是可能小于1的。
Q:数字后加上"*"对打分有何影响,为什么返回结果得分都为1?
A:lucene放弃对score的计算(主要是tf-idf值),1为默认的加权因子boost值。
Q:根据查询结果的得分小于1来过滤结果是否合理?会不会产生新的问题?
A:测试1.1,2.1,2.5中,返回结果的打分小于1,如果根据小于1规则来过滤,就没有结果返回,显然是不对的。
在测试3.3,3.4,3.8,3.10中,查询条件里的布尔逻辑为 OR,排在前面(打分较高)的结果为含有查询条件中term较多的结果,排序越往后的结果往往仅匹配条件中的某个term。如果此时想要的结果能匹配条件中的所有的term,表面上看通过<1来过滤可以达到,其实仅仅是一种巧合。应该通过布尔逻辑AND来保证查询结果命中所有term。
Q:测试2.15中两个查询结果的score不一样?
A:结果1的Explanation:
3.013709 = (MATCH) fieldWeight(content:13932066196 in 18137), product of:
1.0 = tf(termFreq(content:13932066196)=1)
16.073114 = idf(docFreq=2, maxDocs=10550949)
0.1875 = fieldNorm(field=content, doc=18137)
结果2的Explanation:
2.511424 = (MATCH) fieldWeight(content:13932066196 in 24885), product of:
1.0 = tf(termFreq(content:13932066196)=1)
16.073114 = idf(docFreq=2, maxDocs=10550949)
0.15625 = fieldNorm(field=content, doc=24885)
fieldNorm不同,fieldNorm指域的归一化(Normalization)值,表示域中包含的项数量,该值在索引期间计算,并保存在索引的norm中。更短的域(或更少的语汇单元)能获得更大的加权。通过检查查询结果,会发现结果1比结果2的content域内容短。
播发日志查询的要求
1.查询结果不能遗漏也不能增加(“增加”意味着结果里有不匹配的数据)
布尔查询逻辑AND,OR,NOT保证了查询结果完全命中还是部分命中查询条件中的term。
目前已经将BooleanQuery中的BooleanClause布尔子句的occor设置为MUST
if(luceneQuery instanceof BooleanQuery){ BooleanQuery bQuery = (BooleanQuery)luceneQuery; List<BooleanClause> clauses = bQuery.clauses(); for (BooleanClause clause : clauses) { clause.setOccur(Occur.MUST); } }
因为Lucene的Query除了BooleanQuery外还有很多种类型,比如TermRangeQuery、PhraseQuery等,所以建议查询时每个查询子句间显式使用AND,OR,NOT。
2.没有按相关性进行排序的需求
播发日志检索是对日志进行检索,与常用的搜索引擎(google,百度)对查询结果的排序和打分需要不一样。Lucene采用的默认的打分和排序策略与google相似,是对商用搜索引擎的简化。
如果想要进行排序的话,可以采用自定义的排序策略:根据某个域来排序,在我们的应用中可以根据日志时间来排序。
查询结果得分小于1的原因分析
在打分公式中
tf(t in d) = | frequency½ |
其中frequency表示该term出现在待打分文档里的个数,因此tf(t in d)是个大于1的值;
idf(t) = | 1 + log ( | numDocs | |
------------------ | |||
docFreq+1 | ) |
上面idf的值代表了 the inverse of docFreq(term t 出现的文档的数目),通过上面计算公式idf也应该是大于等于1的值;
什么因素可能导致了查询结果的得分小于1呢?
主要与norm(t,d)里的 lengthNorm有关。
lengthNorm表示 computed when the document is added to the index in accordance with(与。。一致) the number of tokens of this field in the document(Field的token的数目), so that shorter fields contribute more to the score.
在默认相似度类DefaultSimilarity 里 lengthNorm 的计算公式如下:
lengthNorm = (float) (1.0 / Math.sqrt(numTerms))
由此计算公式lengthNorm是个小于1的值,通常也是因为 lengthNorm 才使最终结果得分小于1的。
如果想要改变lengthNorm的计算公式或者忽略lengthNorm(lengthNorm=1),该如何做?
在自定义的CustomSimilarity实现类中重写Similarity抽象类中定义的
public float computeNorm(String field, FieldInvertState state)
如果想忽略lengthNorm可以这样写
@Override
public float computeNorm(String field, FieldInvertState state) {
final int numTerms = 1;
return state.getBoost() * numTerms;
{color:#000000}}
还需要告诉IndexWriter使用自定义的CustomSimilarity
indexWriter.setSimilarity(Similarity similarity)
在3.4版本中该方法是过时的,可以在IndexWriterConfig setSimilarity(Similarity similarity)
另外在对query=1065800715 结果的explanation中也能对上述结论得到验证
query=1065800715
0.6772446 = (MATCH) fieldWeight(content:1065800715 in 2200), product of:
1.0 = tf (termFreq(content:1065800715)=1)
3.0959754 = idf (docFreq=1297241, maxDocs=10550949)
0.21875 = fieldNorm (field=content, doc=2200)
0.6772446 = 1.0 * 3.0959754 * 0.21875
至
0.58049536 = (MATCH) fieldWeight(content:1065800715 in 1224258), product of:
1.0 = tf (termFreq(content:1065800715)=1)
3.0959754 = idf (docFreq=1297241, maxDocs=10550949)
0.1875 = fieldNorm (field=content, doc=1224258)
0.58049536 = 1.0 * 3.0959754 * 0.1875
附录
1. lucene 3.4 score机制介绍
http://lucene.apache.org/core/old_versioned_docs//versions/3_4_0/scoring.html
2. lucene 3.4 DefaultSimilarity 打分公式
http://lucene.apache.org/core/old_versioned_docs//versions/3_4_0/api/core/index.html
评论
1.query=1065800715* OR 106580071517
2.query=1065800715
用上面两个query查询,结果里都有打分小于1的document,分析什么因素导致分数小于1。
在query1里,跟 queryNorm, coord有关
在query2里,跟 fieldNorm 有关
分析当查询term里加上*,比如1065800715*,对打分有什么影响?
见http://nemogu.iteye.com/blog/1498262
3.013709 = (MATCH) fieldWeight(content:13932066196 in 18137), product of:
1.0 = tf(termFreq(content:13932066196)=1)
16.073114 = idf(docFreq=2, maxDocs=10550949)
0.1875 = fieldNorm(field=content, doc=18137)
至
2.511424 = (MATCH) fieldWeight(content:13932066196 in 24885), product of:
1.0 = tf(termFreq(content:13932066196)=1)
16.073114 = idf(docFreq=2, maxDocs=10550949)
0.15625 = fieldNorm(field=content, doc=24885)
0.6772446 = (MATCH) fieldWeight(content:1065800715 in 2200), product of:
1.0 = tf(termFreq(content:1065800715)=1)
3.0959754 = idf(docFreq=1297241, maxDocs=10550949)
0.21875 = fieldNorm(field=content, doc=2200)
至
0.58049536 = (MATCH) fieldWeight(content:1065800715 in 1224258), product of:
1.0 = tf(termFreq(content:1065800715)=1)
3.0959754 = idf(docFreq=1297241, maxDocs=10550949)
0.1875 = fieldNorm(field=content, doc=1224258)
1.0 = (MATCH) ConstantScore(content:1065800715*), product of:
1.0 = boost
1.0 = queryNorm
1.7799454 = (MATCH) sum of:
0.13035534 = (MATCH) ConstantScore(content:1065800715*), product of:
1.0 = boost
0.13035534 = queryNorm
1.64959 = (MATCH) weight(content:106580071517 in 900495), product of:
0.9914673 = queryWeight(content:106580071517), product of:
7.6058817 = idf(docFreq=14268, maxDocs=10550949)
0.13035534 = queryNorm
1.6637866 = (MATCH) fieldWeight(content:106580071517 in 900495), product of:
1.0 = tf(termFreq(content:106580071517)=1)
7.6058817 = idf(docFreq=14268, maxDocs=10550949)
0.21875 = fieldNorm(field=content, doc=900495)
至
0.06517767 = (MATCH) product of:
0.13035534 = (MATCH) sum of:
0.13035534 = (MATCH) ConstantScore(content:1065800715*), product of:
1.0 = boost
0.13035534 = queryNorm
0.5 = coord(1/2)
t in q
idf(t) 2 · t.getBoost() · norm(t,d) )
一个查询语句里只有一个token(term)来分析:
tf(t in d)~~1
idf(t) >= 1
norm(t,d) encapsulates a few (indexing time) boost and length factors的值是绝大多数小于1的(主要是length factors小于1) < 1
发表评论
-
【Lucene】建索引核心类介绍
2012-06-08 17:28 1058IndexWriter 负责创建新索引或打开已有索引, ... -
优秀文章汇总
2012-05-08 18:48 766搜索引擎技术之概要预览 http://blog.csd ... -
【Lucene】lucene查询Query对象
2012-05-08 18:41 1412PrefixQuery 前缀查询。 如 test* 会匹配 ... -
【工作】日志检索结果的排序改进分析
2012-04-27 18:07 960下图是现在生产环境的部署图,索引文件分布在70-7 ... -
【Lucene】查询term后加上'*'对打分的影响
2012-04-25 18:14 2093BooleanWeight里sum ... -
lucene.search.Weight
2012-04-25 15:39 992org.apache.lucene.search Cl ... -
lucene.search.Similarity
2012-04-20 10:31 2551Similarity defines the componen ... -
tokenize和tokenizer到底怎么翻译?
2012-03-28 10:32 3575在编写词法分析器(Lexer)或语法分析器(Parse ... -
【Lucene】更合理地使用Document和Field
2012-03-27 09:39 5437writer = ...; //#1 Prepared ... -
【Lucene】构建索引
2012-03-17 23:16 756Lucene索引的过程是什么? step1 收集待 ... -
信息检索类小程序
2012-03-17 00:37 8441.对四大名著txt实现索引和搜索功能 2. -
【Lucene】Scoring
2012-03-13 23:47 1167http://lucene.apache.org/core/o ... -
Information Retrieval
2012-03-13 22:50 998http://wiki.apache.org/lucene-j ... -
【Lucene】lucene的评分机制
2012-03-07 16:24 945测试环境里查询条件1065800714,为什么Score ... -
【Lucene】搜索的核心类简介
2012-03-05 18:48 1383注:Lucene版本为3.4 I ... -
【Lucene】How to make indexing faster
2012-02-16 14:54 822http://wiki.apache.org/lucene-j ... -
【Lucene】index包IndexWriter
2011-12-25 01:50 798Q1:IndexWriter作用是什么? Q2:索引过 ... -
【Lucene】store包SimpleFSDirectory
2011-12-24 23:43 803store包SimpleFSDirectory -
【Lucene】store包FSDirectory
2011-12-24 13:39 1434源码中涉及以下知识点: 1.java.security.Me ... -
【Lucene】store包Directory
2011-12-11 17:23 1317说明 lucene的版本是3.0.3 结构及类图 文件类 ...
相关推荐
同时,它还提供了评分机制,用于衡量查询结果的相关性。 4. **更新与删除** Lucene允许动态更新和删除文档,这在实时搜索场景中非常重要。更新文档时,Lucene会处理旧索引和新索引的合并;删除文档时,它会在索引...
本压缩包包含的是Lucene 3.5.0版本的全部源码,对于想要深入理解Lucene工作原理、进行二次开发或者进行搜索引擎相关研究的开发者来说,是一份非常宝贵的学习资源。 Lucene 3.5.0是Lucene的一个重要版本,它在3.x...
用户可以输入查询语句,工具会显示匹配的文档及其得分,这有助于理解查询评分机制。同时,通过查看查询的执行过程,开发者可以优化查询语句,提高搜索效率。 进一步,该工具可能还包括了对FieldCache、TermVector和...
Lucene 是一个强大的开源全文搜索引擎库,它允许开发者在自己的应用程序中实现高级的搜索功能。...通过深入使用和研究 Luck,我们可以更好地掌握 Lucene 的工作机制,从而构建更高效、更精准的全文搜索系统。
执行查询时,Lucene会使用索引来查找匹配的文档,并根据评分函数(Scoring Function)为每个匹配的文档打分。TF-IDF(Term Frequency-Inverse Document Frequency)是常见的评分算法,它结合了词频和文档频率来衡量...
**Lucene 2.4.0 Jar 包详解** Lucene 是一个开源的全文搜索引擎库,由 Apache 软件基金会开发并维护。这个“lucene-2.4.0 jar 包”是 ...开发者可以利用这个包来构建自己的全文搜索引擎,或者研究 Lucene 的基础功能。
通过阅读`lucene-1.4.3-src`源代码,我们可以深入理解Lucene的内部工作机制,包括索引结构的实现、查询解析的逻辑、相关性评分的计算等。这有助于我们优化搜索引擎性能,解决实际问题,或者为升级到更高版本的Lucene...
在`lucene-1.4-final`这个压缩包中,包含了Lucene 1.4版本的源代码,你可以深入研究其内部实现,理解各个类和方法的工作原理。同时,这也可以帮助你定制分析器、优化搜索性能,或者扩展Lucene的功能,例如集成到你的...
这个过程涉及到布尔查询、短语查询、评分机制等多种复杂逻辑。源码中,我们可以研究如何构建查询解析器和执行引擎,以实现高效且精准的搜索。 此外,Lucene还支持多种高级特性,如faceted search(分面搜索)、...
- **排序与评分**:分析了Lucene中如何根据相关性对搜索结果进行排序,并介绍了不同评分策略的影响。 - **章节6:扩展搜索功能** - **自定义搜索器**:指导读者如何根据实际需求编写自定义搜索器,以增强搜索能力...
4. 搜索优化:学习如何通过Weight和Scorer实现高效的评分和排序机制。 5. 响应处理:了解HitCollector和Collector的用法,以及如何自定义结果集的处理逻辑。 四、实战开发 在实际项目中,开发者可以利用Lucene.NET ...
其核心功能包括文档索引、查询解析、评分机制以及结果排序等。通过Lucene,开发者可以快速地构建出高效的全文搜索引擎。 二、案例解析 1. lucene01_1与lucene01_2 这两个文件可能是两个不同的案例,都涉及到了...
源代码包含了所有类、接口、方法和注释,是学习Lucene内部机制的关键。 4. **关键类和接口**: - `IndexWriter`: 负责创建和更新索引。 - `Analyzer`: 定义了文本分析的规则,如分词器的选择和词形还原等。 - `...
总的来说,Lucene 3.6.2源代码对于那些希望深入研究全文搜索引擎的原理、优化搜索性能或者开发定制化搜索解决方案的开发者来说,是一份宝贵的参考资料。通过对源码的阅读和学习,开发者可以更好地理解和利用Lucene的...
TF-IDF模型是默认的评分算法,但也可以通过自定义ScoreComputation类来实现其他评分机制。 8. **扩展性与可定制化**:Lucene.Net具有良好的模块化设计,开发者可以通过继承和实现接口来扩展其功能,例如自定义分词...
7. **排序与评分**:理解Lucene的评分机制,如TF-IDF,以及如何进行结果排序。 8. **高亮显示**:学习如何使用高亮工具,如`Highlighter`,来突出显示搜索结果中的匹配部分。 9. **性能优化**:探讨如何通过优化...
- **Lucene**:侧重于全文检索,能够处理复杂的自然语言查询,并通过复杂的评分机制来确定文档的相关性。 - **传统数据库系统**:查询通常是基于预定义的字段和值进行精确匹配,不擅长处理模糊或自然语言查询。 ###...
通过深入研究`lucene-3.6.1`的源码,开发者不仅可以掌握Lucene的基础操作,还能理解其内部运作机制,为构建更复杂、高效的搜索引擎打下坚实基础。同时,对于优化搜索性能、定制分析流程、处理特殊数据格式等问题,...
#### 知识点七:Lucene 的案例研究 - **实际应用案例**:书中列举了多个使用 Lucene 解决实际问题的案例,这些案例覆盖了不同行业和应用场景。 - **问题解决思路**:通过对这些案例的学习,读者可以了解到如何利用 ...