原文: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开发介绍 —— 三、索引(四)的更多相关文章

  1. Lucene.Net 2.3.1开发介绍 —— 三、索引(七)

    原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(七) 5.IndexWriter 索引这部分最后讲的是IndexWriter.如果说前面提到的都是数据的结构,那么IndexWriter ...

  2. Lucene.Net 2.3.1开发介绍 —— 三、索引(六)

    原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(六) 2.2 Field的Boost 如果说Document的Boost是一条线,那么Field的Boost则是一个点.怎么理解这个点呢 ...

  3. Lucene.Net 2.3.1开发介绍 —— 三、索引(五)

    原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(五) 话接上篇,继续来说权重对排序的影响.从上面的4个测试,只能说是有个直观的理解了.“哦,是!调整权重是能影响排序了,但是好像没办法来 ...

  4. Lucene.Net 2.3.1开发介绍 —— 三、索引(三)

    原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(三) 3.Field配置所产生的效果 索引数据,简单的代码,只要两个方法就搞定了,而在索引过程中用到的一些类里最简单,作用也不小的就是F ...

  5. Lucene.Net 2.3.1开发介绍 —— 三、索引(二)

    原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(二) 2.索引中用到的核心类 在Lucene.Net索引开发中,用到的类不多,这些类是索引过程的核心类.其中Analyzer是索引建立的 ...

  6. Lucene.Net 2.3.1开发介绍 —— 三、索引(一)

    原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(一) 在说索引之前,先说说索引是什么?为什么要索引?怎么索引? 先想想看,假如现在有一个文本,我们会怎么去搜索.比如,有一个string ...

  7. Lucene.Net 2.3.1开发介绍 —— 四、搜索(三)

    原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(三) Lucene有表达式就有运算符,而运算符使用起来确实很方便,但另外一个问题来了. 代码 4.3.4.1 Analyzer anal ...

  8. Lucene.Net 2.3.1开发介绍 —— 二、分词(三)

    原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(三) 1.3 分词器结构 1.3.1 分词器整体结构 从1.2节的分析,终于做到了管中窥豹,现在在Lucene.Net项目中添加一个类关 ...

  9. Lucene.Net 2.3.1开发介绍 —— 四、搜索(一)

    原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(一) 既然是内容筛选,或者说是搜索引擎,有索引,必然要有搜索.搜索虽然与索引有关,那也只是与索引后的文件有关,和索引的程序是无关的,因此 ...

随机推荐

  1. AIDL使用详解

    一.对AIDL进行说明 AIDL允许定义一个编程的接口来作为客户端和服务端通信的桥梁,AIDL定义了客户端和服务端的编程标准,在Android里边一个进程无法直接访问另一个进程的内存信息,但是要访问的 ...

  2. CSS - ResetCss

    /* KISSY CSS Reset 理念:清除和重置是紧密不可分的 特色:1.适应中文 2.基于最新主流浏览器 */ /* 清除内外边距 */ body, h1, h2, h3, h4, h5, h ...

  3. weblogic中设置数据源的注意点

    一.基本概念 进入weblogic的管理页面,点击服务——>数据源,可以进行数据源的配置.通过新建,输入地址,用户名,密码等信息可以新建一个数据源. 二.发现问题 建立好数据源之后,跑项目,发现 ...

  4. 04-OC属性的使用、自动释放池、封装和继承

    目录: 一.IOS6声明式属性的使用 二.autoreleasepool自动释放池 三.封装.继承 回到顶部 一.IOS6声明式属性的使用 注:声明式属性默认情况下,并没有解决内存问题, 当使用@pr ...

  5. Android TextView(同时显示图片+文字)

    见上图:需要图片和文字 在一起 之前的做法是用两个控件组成 <LinearLayout> <ImageView /> <TextView /> </Linea ...

  6. LoadRunner脚本增强

    1.检查点 web_find() 和web_reg_find() 2.Block技术 如果对不同的事物进行不同次数的循环该怎么处理?默认情况下LoadRunner对所有的事物都是统一执行的,即虽然有多 ...

  7. 怎样在android实现uc和墨迹天气那样的左右拖动效果

    import android.app.Activity; import android.os.Bundle; import android.content.Context; import androi ...

  8. Eclipse用法和技巧二十二:快速调整字体大小

    团队代码review的时候,一般都会一堆人围着显示器,或者投影仪.这个时候调整代码字体大小就显得很重要.下面直接说操作方式.        步骤一:Windows -> Preference 步 ...

  9. 网盘大全, 邮箱大全 good

    网盘推荐 115网盘 注册 百度网盘 注册 微云 注册 360云盘 注册 金山快盘 注册 新浪微盘 注册 和彩云 注册 酷盘 注册 OneDrive 外链 BOX 注册 Dropbox 注册 国内网盘 ...

  10. 【解决方法】System.IO.FileNotFoundException

    错误日志 See the end of this message for details on invoking just-in-time (JIT) debugging instead of thi ...