摘引自:http://www.cnblogs.com/forfuture1978/archive/2010/02/08/1666137.html

Lucene的搜索结果默认按相关度排序,这个相关度排序是基于内部的Score和DocID,Score又基于关键词的内部评分和做索引时的 boost。默认Score高的排前面,如果Score一样,再按索引顺序,先索引的排前面。

Sort groupSort = new Sort(new SortField("排序字段name", SortField.Type.long, true));//true为逆向排序

按字段排序:searcher.search(query, sort)

一:索引阶段设置Document Boost和Field Boost

//Document Boost和Field Boost默认为1。
Document doc = new Document();
Field f = new Field("contents", "hello world", Field.Store.NO, Field.Index.ANALYZED); //Field f = new Field("contents", "hello world", Field.Store.NO, Field.Index.ANALYZED_NO_NORMS);
f.setBoost(100);
doc.add(f);
doc.setBoost(100);

1).Document boost:此值越大,说明此文档越重要。

2).Field boost:此域越大,说明此域越重要。

3).lengthNorm(field) = (1.0 / Math.sqrt(numTerms)):一个域中包含的Term总数越多,也即文档越长,此值越小,文档越短,此值越大。

当设置:Field.Index.ANALYZED_NO_NORMS 第三个因素影响无效

当设置:Field.Index.ANALYZED                   第三个因素影响生效

norms(标准化因子)意义:

没有norms意味着索引阶段禁用了文档boost和域的boost及长度标准化。

好处:在于节省内存,不用在搜索阶段为索引中的每篇文档的每个域都占用一 个字节来保存norms信息了。但是对norms信息的禁用是必须全部域都禁用的,一旦有一个域不禁用,则其他禁用的域也会存放默认的norms值。因为为了加快norms的搜索速度,Lucene是根据文档号乘以每篇文档的norms信息所占用的大小来计算偏移量的,中间少一篇文档,偏移量将无法计算,因为大家知道,偏移是相对来说的,一旦它相对的某篇文档缺失了,那么后面的偏移量也就不复存在了 也即norms信息要么都保存,要么都不保存。

二、在搜索语句中,设置Query Boost.

同域:
title:马德华^4 title:刘德华 这样就人为的干预了搜出来的结果,马德华的结果比较靠前 不同域:
title:马德华^100 content:马德华
title中包含马德华的文档比content中包含马德华的文档获得更高的分数

三、继承并实现自己的Similarity

Similariy是计算Lucene打分的最主要的类,实现其中的很多接口可以干预打分的过程

(1) float computeNorm(String field, FieldInvertState state)

(2) float lengthNorm(String fieldName, int numTokens)

(3) float queryNorm(float sumOfSquaredWeights)

(4) float tf(float freq)

(5) float idf(int docFreq, int numDocs)

(6) float coord(int overlap, int maxOverlap)

(7) float scorePayload(int docId, String fieldName, int start, int end, byte [] payload, int offset, int length)

它们分别影响Lucene打分计算的如下部分:

score(q,d)   =   (6)coord(q,d)  ·  (3)queryNorm(q)  · ( (4)tf(t in d)  ·  (5)idf(t)2  ·  t.getBoost() ·  (1)norm(t,d) )
t in q

norm(t,d)   =   doc.getBoost()  ·  (2)lengthNorm(field)  ·  f.getBoost() field f in d named as t

(1) float computeNorm(String field, FieldInvertState state)

影响标准化因子的计算,如上述,他主要包含了三部分:文档boost,域boost,以及文档长度归一化。此函数一般按照上面norm(t, d)的公式进行计算。

(2) float lengthNorm(String fieldName, int numTokens)

在一篇1000万个词的鸿篇巨著中,"lucene"这个词出现了11次,而在一篇12个词的短小文档中,"lucene"这个词出现了10次,如果不考虑长度在内,当然鸿篇巨著应该分数更高,然而显然这篇小文档才是真正关注"lucene"的。因而在此处是要除以文档的长度,从而减少因文档长度带来的打分不公。

但是实际情况是需要灵活多变的,所以文档长度也需要自己控制下,比如我想做一个经济学论文的搜索系统,经过一定时间的调研,发现大多数的经济学论文的长度在8000到10000词,因而lengthNorm的公式应该 是一个倒抛物线型的,8000到10000词的论文分数最高,更短或更长的分数都应该偏低,方能够返回给用户最好的数据。

(3) float queryNorm(float sumOfSquaredWeights)

这是按照向量空间模型,对query向量的归一化。此值并不影响排序,而仅仅使得不同的query之间的分数可以比较。

(4) float tf(float freq)

freq是指在一篇文档中包含的某个词的数目。tf是根据此数目给出的分数,默认为Math.sqrt(freq)。也即此项并不是随着包含的数目的增多而线性增加的。

Math.sqrt(freq); freq开平方

(5) float idf(int docFreq, int numDocs)

idf是根据包含某个词的文档数以及总文档数计算出的分数,默认为(Math.log(numDocs/(double)(docFreq+1)) + 1.0)。

由于此项计算涉及到总文档数和包含此词的文档数,因而需要全局的文档数信息,这给跨索引搜索造成麻烦。

从下面的例子我们可以看出,用MultiSearcher来一起搜索两个索引和分别用IndexSearcher来搜索两个索引所得出的分数是有很大差异的。

(6) float coord(int overlap, int maxOverlap)

一次搜索可能包含多个搜索词,而一篇文档中也可能包含多个搜索词,此项表示,当一篇文档中包含的搜索词越多,则此文档则打分越高。

(7) float scorePayload(int docId, String fieldName, int start, int end, byte [] payload, int offset, int length)

由于Lucene引入了payload,因而可以存储一些自己的信息,用户可以根据自己存储的信息,来影响Lucene的打分。

四、继承并实现自己的collector

Lucene 对文档打分的规则整理记录的更多相关文章

  1. 有关Lucene的问题(4):影响Lucene对文档打分的四种方式

    原文出自:http://forfuture1978.iteye.com/blog/591804点击打开链接 在索引阶段设置Document Boost和Field Boost,存储在(.nrm)文件中 ...

  2. 用Lucene对文档进行索引搜索

    问题 现在给出很多份文档,现在对某个搜索词感兴趣,想找到相关的文档. 简单搜索 一种简单粗暴的做法是: 1.读取每个文档:2.找到其中含有搜索词的文档:3.对找到的文档中搜索词出现的次数统计:4.根据 ...

  3. 2019年最新总结,从程序员到CTO,从专业走向卓越,大牛分享文档pdf与PPT整理

    整理大牛分享文档如下,持续更新一线开发架构,技术文档 github链接 网易蜂巢公有容器云架构之路 新浪微博redis优化历程 微博Cache架构设计实践 Go在大数据开发中的经验总结 基于Go构建滴 ...

  4. 【资源】108个大数据文档PDF开放下载-整理后打包下载

                  本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html        本博客其他.NET开源项目文章目录:h ...

  5. LotusScript_文档查询循环方法整理

    1.  视图(View)查询 ... Set view = db.GetView("ViewName") Set doc = view.GetFirstDocument While ...

  6. 转: seajs手册与文档之 -- require规则

    require 规则 正确拼写 不要修改 使用直接量 动态依赖的小提示 书写规则 使用 SeaJS 书写模块代码时,需要遵循一些简单规则: 1. 正确拼写 在模块代码中,第一个参数 必须 命名为 re ...

  7. antd模块组件文档思维导图整理

  8. 学习Java爬虫文档的学习顺序整理

    1.认识正则表达式(Java语言基础) https://www.toutiao.com/i6796233686455943693/ 2.正则表达式学习之简单手机号和邮箱练习 https://www.t ...

  9. openWRT自学---对官方的开发指导文档的解读和理解 记录3:一些常用方法

    1.约定 configuration files follow the convention:  <name>.conf init files follow the convention: ...

随机推荐

  1. ALAssets的两种用法

    一: ALAssetsGroupEnumerationResultsBlock resultsBlock = ^(ALAsset *result, NSUInteger index, BOOL *st ...

  2. 属性的定义以及@synthesize的使用

    1.属性通常是指某些由对象封装或储存的数据.它可以是标志(如名称或颜色),也可以是与一个或多个其他对象的关系. 2.属性的基本声明使用 @property 编译器指令,后面紧跟属性的类型信息和名称.您 ...

  3. 【LeetCode OJ】Surrounded Regions

    Problem Link: http://oj.leetcode.com/problems/surrounded-regions/ We can do follows in the 2D board. ...

  4. PHP Forms

    <html><body><form action="welcome.php" method="post">Name: < ...

  5. 钱币兑换问题_完全背包&&拆分&&母函数

    ps:原来用新浪,可是代码的排版不是很好,所以用博客园啦,先容许我把从八月份开始的代码搬过来,从这里重新出发,希望这里可以一直见证我的成长. Time Limit: 2000/1000 MS (Jav ...

  6. 为什么要urlencode

    为什么要urlencode  1.为了正常获取值  字符 特殊字符的含义 URL编码 & 分隔不同的变量值对 %26 = 用来连接键和值 %3D ? 表示查询字符串的开始 %3F # 用来标志 ...

  7. 重学STM32---(四)

    今天把定时器看了一遍,觉得很有必要把记下来时常看一看 定时器3初始化,很简单,开时钟,装载ARR,PSC寄存器就行了,想要开什么中断在DIER寄存器设置就行了(不过当时我花了很长时间,用寄存器真的不熟 ...

  8. 让UIWebView弹出键盘上的按钮显示中文

    UIWebView是一个很常用的视图,一般用来加载网页,比如百度: 点击文本框输入框后,会弹出一个带有toolbar的键盘,toolbar中有3个辅助按钮 有了这3个按钮,是方便很多,但默认是英文的, ...

  9. Oracle PL/SQL高级应用 游标

    游标可以处理SQL语句查询出来的结果集,进行逐条控制,其实游标在内存中申请空间,将自己指向SQL语句查询出来的结果集,有点像指针的感觉,游标使SQL更加的灵活. DECLARE CURSOR mycu ...

  10. 这是高手最常用的第一快捷组合键 - imsoft.cnblogs

    1.锁定电脑 2.要找电脑上的文件时,一般人会先找到“我的电脑”,然后点击打开,而高手总是很酷的,轻轻按下键盘上的Windows键不放然后再按E键,直接打开电脑的资源管理器,而一般人还在慢慢寻找“我的 ...