Lucene的评分(score)机制的简单解释

  • 博客分类:
  • Lucene
lucene编程Apachethread 
通过Searcher.explain(Query query, int doc)方法可以查看某个文档的得分的具体构成。

在Lucene中score简单说是由 tf * idf * boost * lengthNorm计算得出的。

tf:是查询的词在文档中出现的次数的平方根
idf:表示反转文档频率,观察了一下所有的文档都一样,所以那就没什么用处,不会起什么决定作用。
boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值会同时起作用
lengthNorm:是由搜索的field的长度决定了,越长文档的分值越低。

所以我们编程能够控制score的就是设置boost值。

还有个问题,为什么一次查询后最大的分值总是1.0呢?
因为Lucene会把计算后,最大分值超过1.0的分值作为分母,其他的文档的分值都除以这个最大值,计算出最终的得分。

下面用代码和运行结果来进行说明:

Java代码  
  1. public class ScoreSortTest {
  2. public final static String INDEX_STORE_PATH = "index";
  3. public static void main(String[] args) throws Exception {
  4. IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true);
  5. writer.setUseCompoundFile(false);
  6. Document doc1 = new Document();
  7. Document doc2 = new Document();
  8. Document doc3 = new Document();
  9. Field f1 = new Field("bookname","bc bc", Field.Store.YES, Field.Index.TOKENIZED);
  10. Field f2 = new Field("bookname","ab bc", Field.Store.YES, Field.Index.TOKENIZED);
  11. Field f3 = new Field("bookname","ab bc cd", Field.Store.YES, Field.Index.TOKENIZED);
  12. doc1.add(f1);
  13. doc2.add(f2);
  14. doc3.add(f3);
  15. writer.addDocument(doc1);
  16. writer.addDocument(doc2);
  17. writer.addDocument(doc3);
  18. writer.close();
  19. IndexSearcher searcher = new IndexSearcher(INDEX_STORE_PATH);
  20. TermQuery q = new TermQuery(new Term("bookname", "bc"));
  21. q.setBoost(2f);
  22. Hits hits = searcher.search(q);
  23. for(int i=0; i<hits.length();i++){
  24. Document doc = hits.doc(i);
  25. System.out.print(doc.get("bookname") + "\t\t");
  26. System.out.println(hits.score(i));
  27. System.out.println(searcher.explain(q, hits.id(i)));//
  28. }
  29. }
  30. }
public class ScoreSortTest {public final static String INDEX_STORE_PATH = "index";public static void main(String[] args) throws Exception {IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true);writer.setUseCompoundFile(false);Document doc1 = new Document();Document doc2 = new Document();Document doc3 = new Document();Field f1 = new Field("bookname","bc bc", Field.Store.YES, Field.Index.TOKENIZED);Field f2 = new Field("bookname","ab bc", Field.Store.YES, Field.Index.TOKENIZED);Field f3 = new Field("bookname","ab bc cd", Field.Store.YES, Field.Index.TOKENIZED);doc1.add(f1);doc2.add(f2);doc3.add(f3);writer.addDocument(doc1);writer.addDocument(doc2);writer.addDocument(doc3);writer.close();IndexSearcher searcher = new IndexSearcher(INDEX_STORE_PATH);TermQuery q = new TermQuery(new Term("bookname", "bc"));q.setBoost(2f);Hits hits = searcher.search(q);for(int i=0; i<hits.length();i++){Document doc = hits.doc(i);System.out.print(doc.get("bookname") + "\t\t");System.out.println(hits.score(i));System.out.println(searcher.explain(q, hits.id(i)));//}}
}

运行结果:

引用
bc bc 0.629606
0.629606 = (MATCH) fieldWeight(bookname:bc in 0), product of:
  1.4142135 = tf(termFreq(bookname:bc)=2)
  0.71231794 = idf(docFreq=3, numDocs=3)
  0.625 = fieldNorm(field=bookname, doc=0)

ab bc 0.4451987
0.4451987 = (MATCH) fieldWeight(bookname:bc in 1), product of:
  1.0 = tf(termFreq(bookname:bc)=1)
  0.71231794 = idf(docFreq=3, numDocs=3)
  0.625 = fieldNorm(field=bookname, doc=1)

ab bc cd 0.35615897
0.35615897 = (MATCH) fieldWeight(bookname:bc in 2), product of:
  1.0 = tf(termFreq(bookname:bc)=1)
  0.71231794 = idf(docFreq=3, numDocs=3)
  0.5 = fieldNorm(field=bookname, doc=2)

从结果中我们可以看到:
bc bc文档中bc出现了2次,tf为2的平方根,所以是1.4142135。而其他的两个文档出现了一次,所以是1.0
所有的三个文档的idf值都是一样的,是0.71231794
默认情况下,boost的值都是1.0,所以lengthNorm就是当前的fieldNorm的值。前两个文档的长度一致,为0.625,而排在最后的文档,因为长度要长一些,所以分值要低,为0.5

现在对f2这个字段增加激励因子:f2.setBoost(2.0f);
运行结果变为:

引用
ab bc 0.8903974
0.8903974 = (MATCH) fieldWeight(bookname:bc in 1), product of:
  1.0 = tf(termFreq(bookname:bc)=1)
  0.71231794 = idf(docFreq=3, numDocs=3)
  1.25 = fieldNorm(field=bookname, doc=1)

发现fieldNorm值有0.625变成了1.25,所以就是乘以了2.0

接下来再对第二个文档增加激励因子:doc2.setBoost(2.0f);
运行结果变为:

引用
ab bc 1.0
1.7807949 = (MATCH) fieldWeight(bookname:bc in 1), product of:
  1.0 = tf(termFreq(bookname:bc)=1)
  0.71231794 = idf(docFreq=3, numDocs=3)
  2.5 = fieldNorm(field=bookname, doc=1)

发现fieldNorm又乘以了2,所以说对于Document和Field的setBoost都会乘到一起。

因为该文档的最终的score超过了1.0变成1.7807949,所以其他的两个文档的最终得分都要除以该值,
分别变成:

引用
bc bc 0.35355335
ab bc cd 0.19999999

相信通过上面的解释,大家就可以形象得理解Lucene的打分机制,同时也知道如何来改变文档的得分。

Lucene的评分(score)机制的简单解释相关推荐

  1. Lucene的评分(score)机制研究

    首先,需要学习Lucene的评分计算公式-- 分值计算方式为查询语句q中每个项t与文档d的匹配分值之和,当然还有权重的因素.其中每一项的意思如下表所示: 表3.5 评分公式中的因子 评分因子 描 述 ...

  2. 《深入理解Elasticsearch(原书第2版)》——第2章 查询DSL进阶 2.1 Apache Lucene默认评分公式解释...

    本节书摘来自华章计算机<深入理解Elasticsearch(原书第2版)>一书中的第2章,第2.1节,作者 [美]拉斐尔·酷奇(Rafal Ku)马雷克·罗戈任斯基(Marek Rogoz ...

  3. 如何简单解释 MapReduce算法

    原文地址:如何简单解释 MapReduce 算法 在Hackbright做导师期间,我被要求向技术背景有限的学生解释MapReduce算法,于是我想出了一个有趣的例子,用以阐释它是如何工作的. 例子 ...

  4. 教ai玩游戏_简单解释:DeepMind如何教AI玩视频游戏

    教ai玩游戏 by Aman Agarwal 通过阿曼·阿加瓦尔(Aman Agarwal) 简单解释:DeepMind如何教AI玩视频游戏 (Explained Simply: How DeepMi ...

  5. iOS学习重要知识点整理02-进程和线程的一个简单解释

    http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html 阮一峰的网络日志 » 首页 » 档案 上一篇:熵的社会学意义 下一篇 ...

  6. javascript迭代器_JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释...

    javascript迭代器 by rajaraodv 通过rajaraodv JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释 (JavaScript Symbols, ...

  7. 【Java面试题】21 Java中的异常处理机制的简单原理和应用。

    [Java面试题]21 Java中的异常处理机制的简单原理和应用. 参考文章: (1)[Java面试题]21 Java中的异常处理机制的简单原理和应用. (2)https://www.cnblogs. ...

  8. 利用JDK动态代理机制实现简单拦截器

    利用JDK动态代理机制实现简单的多层拦截器 首先JDK动态代理是基于接口实现的,所以我们先定义一个接口 public interface Executer {public Object execute ...

  9. 常用CSS元素div ul dl dt ol的简单解释

    几个css元素的简单解释 div ul dl dt oldiv,这个很常见,块级元素,div尽量少用,和table一样,嵌套越少越好 ol 有序列表. <ol> <li>--& ...

最新文章

  1. Java8中一个极其强悍的新特性,很多人没用过(非常实用)
  2. unix系统mysql卸载教程_Linux操作系统下MySQL的卸载、安装全过程
  3. 转载 — 问题解决:Unlink of file '.git/objects/pack/pack-***.pack' failed. Should I try again? (y/n) y
  4. ubuntu 18.04 melodic roslaunch :七步使用roslaunch控制两个终端机器人
  5. scrapy里的selector,不能有正则提取
  6. jquery背景动画插件使用
  7. paip. JAVA快速开发IDE与JSF技术
  8. C++中的gotoxy函数
  9. c语言ide 字体大小,配置最小c语言IDE
  10. Java开发的第一个开源项目
  11. exosip鉴权及使用
  12. axure怎么制作聊天页面
  13. 燕十八-PHP公益培训-学习
  14. 各级国家机关推广应用电子印章相关政策汇总
  15. android ios 实时视频,Twitter推出适用于Android和iOS设备的实时视频
  16. Python爬虫基础-mysql数据库
  17. AD账号被频繁锁定的解决方案
  18. C++面试题,阿里、百度、腾讯、华为、小米100道C++面试题目及答案
  19. SPSS正版中文版 | SPSS软件下载安装| SPSS软件功能使用
  20. 【MySql 数据库综合练习04】

热门文章

  1. vue暴露的全局方法_Vue中实现全局方法
  2. javabirdge php_PHP-Java-Bridge使用笔记,2014年9月最新版
  3. html显示后台传来的byte类型的数据_java的数据类型
  4. c语言文件查找函数fread,文件函数fread
  5. mysql 5.5 5.6 主从_mysql5.6+主从集的版本号(mysql5.5主机和从机载带后,5.5在设置有一定的差距)...
  6. python提取字符串中的 中文 日文 韩文
  7. cifar-10 cnn 分类
  8. MATLAB实战系列(十四)-如何通过YALMIP和CPLEX求解小规模(CVRP)路径调度问题(附MATLAB代码)
  9. 过拟合(原因、解决方案、原理)
  10. xss绕过字符过滤_XSS过滤器绕过总结