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

简介: 原文:Lucene.Net 2.3.1开发介绍 —— 三、索引(四)4、索引对搜索排序的影响   搜索的时候,同一个搜索关键字和同一份索引,决定了一个结果,不但决定了结果的集合,也确定了结果的顺序。
原文: 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;
10
11namespace Test
12{
13    [TestFixture]
14    public class StandardAnalyzerCaseTest
15    {
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        }

32
33        /**//// <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);
47
48                Console.WriteLine(doc.Get("content"+ "_得分:" + hits.Score(i).ToString("f2"));
49            }

50        }

51
52        /**//// <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包含相同词数的文档估计也不是很多。那这样区分有什么意义呢?

目录
相关文章
|
23天前
|
Linux API C#
基于 .NET 开发的多功能流媒体管理控制平台
基于 .NET 开发的多功能流媒体管理控制平台
38 9
|
25天前
|
缓存 算法 安全
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
64 12
|
23天前
|
Web App开发 前端开发 调度
一款基于 .NET + Blazor 开发的智能访客管理系统
一款基于 .NET + Blazor 开发的智能访客管理系统
|
23天前
|
前端开发 JavaScript C#
基于.NET8+Vue3开发的权限管理&个人博客系统
基于.NET8+Vue3开发的权限管理&个人博客系统
|
23天前
|
网络协议 C#
基于.NET WinForm开发的一款硬件及协议通讯工具
基于.NET WinForm开发的一款硬件及协议通讯工具
|
23天前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
|
2月前
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
51 4
|
4月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
56 7

热门文章

最新文章