Lucene.Net 2.3.1开发介绍 —— 三、索引(四)
原文:Lucene.Net 2.3.1开发介绍 —— 三、索引(四)
4、索引对搜索排序的影响
搜索的时候,同一个搜索关键字和同一份索引,决定了一个结果,不但决定了结果的集合,也确定了结果的顺序。那个这个结果是怎么得出来的?这个顺序又是怎么排的呢?这两个问题不是本节讨论的重点,但是这两个问题却关系到本节要讨论的,索引对结果的影响问题。在不使用字段排序的情况下,Lucene.Net默认是按文档的得分来排序的,这个公式看着很复杂,感觉像是大学时高数书上的那些个公式,其实说清楚了也简单。
关于文档排序有几个要素:
(1)、查询词在文档中出现的频率,就是一个文档中包含了几个查询词,然后再开个平方,这个很好理解;
(2)、反转文档频率,这个复杂一点。影响它的有两个因素,一个是包含查询词的文档总数,一个是文档的整体数量。比如,现在的索引文件有1000个文档,而现在搜索的关键字“博客园”,能找到499个文档包含它。那么就会拿文档总数除以包含关键字的文档数,这里包含关键字的文档数加了1,是防止一个也没找到,出现除以0的情况。这样,在这个例子中,就会得到结果2。然后再对这个2进行log操作,操作完了再加1。这样就得到值了。可以看出,文档总数越多,包含关键字的文档越少,那么这个值就越大。
(3)、权重,很多书上叫激励因子,我喜欢叫权重。这个就是我们索引的时候能够调整的值。本节也就是对这个分析。
(4)、保有率。这个名字比较难起,我就照着城市汽车保有率起一个吧。意思呢就是,按照分词结果,一个Field如果含有100个词,那么就会把100开平方,得到10,然后再拿1除以这个10,得到0.1。
这里就不详细论述了,下面进入本节的重点。
1、什么是索引的权重?
从上面看出,有4个部分影响了文档的得分,那么,它们是乘积关系,所以权重对文档排序影响很大。什么是权重呢?就是你可以根据文档内容的好坏,设置好的文档权重高,设置差的文档权重低,是一个调节排序的因子,而不用在搜索是按字段排序。
2、怎么调整权重?
在Lucene.Net中怎么调整权重呢?在不修改评分公式的前提下,可以通过设置Boost来控制权重的值。这个过程在索引文档的时候就进行了,一旦文档被写入,这个值就不可更改了,除非删了重新建一个。调整权重也有两种调法,来仔细分析下设置权重如何影响排序的。
2.1 Document的boost
对以前的代码做个修改,变成代码2.1.1。
代码2.1.1 1using System; 2using System.Collections.Generic; 3using Lucene.Net.Analysis; 4using Lucene.Net.Analysis.Standard; 5using Lucene.Net.Documents; 6using Lucene.Net.Index; 7using Lucene.Net.QueryParsers; 8using Lucene.Net.Search; 9using NUnit.Framework;1011namespace Test12{13 [TestFixture]14 public class StandardAnalyzerCaseTest15 {16 /**//// <summary>17 /// 执行测试的入口18 /// </summary>19 [Test]20 public void SearcherTest()21 {22 Index();23 List<string> list = new List<string>() { "测试" };24 for (int i = 0; i < list.Count; i++)25 {26 Console.WriteLine("搜索词:" + list[i]);27 Console.WriteLine("结果:");28 Searcher(list[i]);29 Console.WriteLine("-----------------------------------");30 }31 }3233 /**//// <summary>34 /// 搜索35 /// </summary>36 /// <param name="querystring">搜索输入</param>37 private void Searcher(string querystring)38 {39 Analyzer analyzer = new StandardAnalyzer();40 IndexSearcher searcher = new IndexSearcher("IndexDirectory");41 QueryParser parser = new QueryParser("content", analyzer);42 Query query = parser.Parse(querystring);43 Hits hits = searcher.Search(query);44 for (int i = 0; i < hits.Length(); i++)45 {46 Document doc = hits.Doc(i);4748 Console.WriteLine(doc.Get("content") + "_得分:" + hits.Score(i).ToString("f2"));49 }50 }5152 /**//// <summary>53 /// 索引数据54 /// </summary>55 private void Index()56 {57 Analyzer analyzer = new StandardAnalyzer();58 IndexWriter writer = new IndexWriter("IndexDirectory", analyzer, true);59 AddDocument(writer, "测试标题一", "测试内容一", 1.0f);60 AddDocument(writer, "测试标题二", "测试内容二", 1.0f);61 AddDocument(writer, "测试标题三", "测试内容三", 1.0f);62 AddDocument(writer, "测试标题四", "测试内容四", 1.0f);63 writer.Optimize();64 writer.Close();65 }66 /**//// <summary>67 /// 为索引准备数据68 /// </summary>69 /// <param name="writer">索引实例</param>70 /// <param name="content">需要索引的数据</param>71 void AddDocument(IndexWriter writer, string title, string content, float boost)72 {73 Document document = new Document();74 document.Add(new Field("title", title, Field.Store.YES, Field.Index.TOKENIZED));75 document.Add(new Field("content", content, Field.Store.YES, Field.Index.TOKENIZED));76 document.SetBoost(boost);77 writer.AddDocument(document);78 }79 }80}
测试,输出:
搜索词:测试
结果:
测试内容一_得分:0.68
测试内容二_得分:0.68
测试内容三_得分:0.68
测试内容四_得分:0.68
-----------------------------------
这个在预料之中,在得分相同的情况下,是按照加入的顺序排的。现在把索引部分代码换成代码 2.1.2。
代码2.1.2 1/**//// <summary> 2/// 索引数据 3/// </summary> 4private void Index() 5{ 6 Analyzer analyzer = new StandardAnalyzer(); 7 IndexWriter writer = new IndexWriter("IndexDirectory", analyzer, true); 8 AddDocument(writer, "测试标题一", "测试内容一111", 1.0f); 9 AddDocument(writer, "测试标题二", "测试内容二11", 1.0f);10 AddDocument(writer, "测试标题三", "测试内容三1", 1.0f);11 AddDocument(writer, "测试标题四", "测试内容四", 1.0f);12 writer.Optimize();13 writer.Close();14}
测试结果:
搜索词:测试
结果:
测试内容四_得分:0.68
测试内容一111_得分:0.58
测试内容二11_得分:0.58
测试内容三1_得分:0.58
-----------------------------------
-----------------------------------
因为数字部分都是同一个分词,所以前三个都一样,这个也好理解,这样就理解了为什么一般文字越多,排得越后了。现在词的数量较少,改变数量对得分影响极大。
现在对boost的值调整一下,变成代码2.1.3。
代码2.1.3 1/**//// <summary> 2/// 索引数据 3/// </summary> 4private void Index() 5{ 6 Analyzer analyzer = new StandardAnalyzer(); 7 IndexWriter writer = new IndexWriter("IndexDirectory", analyzer, true); 8 AddDocument(writer, "测试标题一", "测试内容一111", 1.3f); 9 AddDocument(writer, "测试标题二", "测试内容二11", 1.2f);10 AddDocument(writer, "测试标题三", "测试内容三1", 1.1f);11 AddDocument(writer, "测试标题四", "测试内容四", 1.0f);12 writer.Optimize();13 writer.Close();14}
测试结果:
搜索词:测试
结果:
测试内容一111_得分:0.78
测试内容二11_得分:0.68
测试内容三1_得分:0.68
测试内容四_得分:0.68
-----------------------------------
似乎,调整得小了点,结果影响并不是很大,只有调成1.3的对结果造成了比较大的影响,是不是调成1.3以上就会对结果产生比较大的影响呢?来试试代码2.1.4。
代码2.1.4 1/**//// <summary> 2/// 索引数据 3/// </summary> 4private void Index() 5{ 6 Analyzer analyzer = new StandardAnalyzer(); 7 IndexWriter writer = new IndexWriter("IndexDirectory", analyzer, true); 8 AddDocument(writer, "测试标题一", "测试内容一111", 1.3f); 9 AddDocument(writer, "测试标题二", "测试内容二11", 1.4f);10 AddDocument(writer, "测试标题三", "测试内容三1", 1.5f);11 AddDocument(writer, "测试标题四", "测试内容四", 1.6f);12 writer.Optimize();13 writer.Close();14}
果然,尤其是文档含有词少的,影响更加明显,评分结果:
搜索词:测试
结果:
测试内容四_得分:0.97
测试内容一111_得分:0.78
测试内容二11_得分:0.78
测试内容三1_得分:0.78
-----------------------------------
现在先对以上数据分析一下,不难看出,得分越高的,对权重的敏感度越高,而相同的,就会比较迟钝。这样一般达不到我们想要的目地。当然在文档索引过程中出现索引文档Field包含相同词数的文档估计也不是很多。那这样区分有什么意义呢?
Lucene.Net 2.3.1开发介绍 —— 三、索引(四)的更多相关文章
- Lucene.Net 2.3.1开发介绍 —— 三、索引(七)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(七) 5.IndexWriter 索引这部分最后讲的是IndexWriter.如果说前面提到的都是数据的结构,那么IndexWriter ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(六)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(六) 2.2 Field的Boost 如果说Document的Boost是一条线,那么Field的Boost则是一个点.怎么理解这个点呢 ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(五)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(五) 话接上篇,继续来说权重对排序的影响.从上面的4个测试,只能说是有个直观的理解了.“哦,是!调整权重是能影响排序了,但是好像没办法来 ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(三)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(三) 3.Field配置所产生的效果 索引数据,简单的代码,只要两个方法就搞定了,而在索引过程中用到的一些类里最简单,作用也不小的就是F ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(二)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(二) 2.索引中用到的核心类 在Lucene.Net索引开发中,用到的类不多,这些类是索引过程的核心类.其中Analyzer是索引建立的 ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(一)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(一) 在说索引之前,先说说索引是什么?为什么要索引?怎么索引? 先想想看,假如现在有一个文本,我们会怎么去搜索.比如,有一个string ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(三)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(三) Lucene有表达式就有运算符,而运算符使用起来确实很方便,但另外一个问题来了. 代码 4.3.4.1 Analyzer anal ...
- Lucene.Net 2.3.1开发介绍 —— 二、分词(三)
原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(三) 1.3 分词器结构 1.3.1 分词器整体结构 从1.2节的分析,终于做到了管中窥豹,现在在Lucene.Net项目中添加一个类关 ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(一)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(一) 既然是内容筛选,或者说是搜索引擎,有索引,必然要有搜索.搜索虽然与索引有关,那也只是与索引后的文件有关,和索引的程序是无关的,因此 ...
随机推荐
- AIDL使用详解
一.对AIDL进行说明 AIDL允许定义一个编程的接口来作为客户端和服务端通信的桥梁,AIDL定义了客户端和服务端的编程标准,在Android里边一个进程无法直接访问另一个进程的内存信息,但是要访问的 ...
- CSS - ResetCss
/* KISSY CSS Reset 理念:清除和重置是紧密不可分的 特色:1.适应中文 2.基于最新主流浏览器 */ /* 清除内外边距 */ body, h1, h2, h3, h4, h5, h ...
- weblogic中设置数据源的注意点
一.基本概念 进入weblogic的管理页面,点击服务——>数据源,可以进行数据源的配置.通过新建,输入地址,用户名,密码等信息可以新建一个数据源. 二.发现问题 建立好数据源之后,跑项目,发现 ...
- 04-OC属性的使用、自动释放池、封装和继承
目录: 一.IOS6声明式属性的使用 二.autoreleasepool自动释放池 三.封装.继承 回到顶部 一.IOS6声明式属性的使用 注:声明式属性默认情况下,并没有解决内存问题, 当使用@pr ...
- Android TextView(同时显示图片+文字)
见上图:需要图片和文字 在一起 之前的做法是用两个控件组成 <LinearLayout> <ImageView /> <TextView /> </Linea ...
- LoadRunner脚本增强
1.检查点 web_find() 和web_reg_find() 2.Block技术 如果对不同的事物进行不同次数的循环该怎么处理?默认情况下LoadRunner对所有的事物都是统一执行的,即虽然有多 ...
- 怎样在android实现uc和墨迹天气那样的左右拖动效果
import android.app.Activity; import android.os.Bundle; import android.content.Context; import androi ...
- Eclipse用法和技巧二十二:快速调整字体大小
团队代码review的时候,一般都会一堆人围着显示器,或者投影仪.这个时候调整代码字体大小就显得很重要.下面直接说操作方式. 步骤一:Windows -> Preference 步 ...
- 网盘大全, 邮箱大全 good
网盘推荐 115网盘 注册 百度网盘 注册 微云 注册 360云盘 注册 金山快盘 注册 新浪微盘 注册 和彩云 注册 酷盘 注册 OneDrive 外链 BOX 注册 Dropbox 注册 国内网盘 ...
- 【解决方法】System.IO.FileNotFoundException
错误日志 See the end of this message for details on invoking just-in-time (JIT) debugging instead of thi ...