关于Lucene全文检索相关技术

摘要:
Lucene技术是专门为解决海量数据下的模糊搜索问题而设计的。Lucene主要负责数据预处理、构建反向索引、搜索、排名、突出显示等功能。全文检索相关单词摘要:单词和文档矩阵:文档:索引库中的原始数据,例如网页、产品文档编号(DocID):当索引库存储文档时,它将根据文档创建时间对文档进行编号,这称为文档编号单词(term):

Lucene技术专门解决海量数据下的模糊搜索问题。

Lucene主要完成的是数据预处理、建立倒排索引,及搜索、排名、高亮显示等功能

全文检索相关词语概要:

单词和文档矩阵:

         文档(Document):就是索引库中的一条原始数据,比如一个网页,一件商品

         文档编号(DocID):索引库存储文档时,会根据文档创建时间,进行编号,称为文档编号

         单词(term):就是对原始数据中的文本进行分词,得到的每一个词条

文档列表:把原始数据,及其编号形成一个列表,称为文档列表        

 关于Lucene全文检索相关技术第1张

倒排索引列表:以单词及单词编号为索引,保存包含该单词的所有文档的文档编号,形成的列表。

关于Lucene全文检索相关技术第2张

倒排索引的流程:

  1. 创建索引的过程:

    A:创建文档列表:给所有的文档形成编号,然后以编号为索引保存所有的文档数据

    B:创建倒排索引列表:以所有的词条为索引,然后保存包含该词条的所有文档的编号信息。形成的列表

  2. 搜索的过程:

         当用户输入一个词条,我们会先去倒排索引列表快速定位到这个词条,然后就能知道包含该词条的所有文档的编号。然后就能快速根据编号找到文档

1、Lucene的概述

1.1、什么是Lucene?

1. Lucene是一套用于全文检索和搜寻的开源程序库,由Apache软件基金会支持和提供

2. Lucene提供了一个简单却强大的应用程序接口(API),能够做全文索引和搜寻,在Java开发环境里Lucene是一个成熟的免费开放源代码工具

3. Lucene并不是现成的搜索引擎产品,但可以用来制作搜索引擎产品

官网:http://lucene.apache.org/

1.2、什么是全文检索?

关于Lucene全文检索相关技术第3张

1.3、Lucene和Solr的关系

1. Lucene:一套实现了全文检索的底层API

2. Solr:基于Lucene开发的企业级搜索应用服务器

1.4、Lucene的基本使用

使用Lucene实现索引库的增(创建索引)、删(删除索引)、改(修改索引)、查(搜索数据)。

2.1、使用Lucene创建索引

2.1.1、添加依赖

 1 <!-- Junit单元测试 -->
 2 <dependency>
 3     <groupId>junit</groupId>
 4     <artifactId>junit</artifactId>
 5     <version>4.12</version>
 6 </dependency>
 7 <!-- lucene核心库 -->
 8 <dependency>
 9     <groupId>org.apache.lucene</groupId>
10     <artifactId>lucene-core</artifactId>
11     <version>4.10.2</version>
12 </dependency>
13 <!-- Lucene的查询解析器 -->
14 <dependency>
15     <groupId>org.apache.lucene</groupId>
16     <artifactId>lucene-queryparser</artifactId>
17     <version>4.10.2</version>
18 </dependency>
19 <!-- lucene的默认分词器库 -->
20 <dependency>
21     <groupId>org.apache.lucene</groupId>
22     <artifactId>lucene-analyzers-common</artifactId>
23     <version>4.10.2</version>
24 </dependency>
25 <!-- lucene的高亮显示 -->
26 <dependency>
27     <groupId>org.apache.lucene</groupId>
28     <artifactId>lucene-highlighter</artifactId>
29     <version>4.10.2</version>
30 </dependency>
31 
32 <build>
33     <plugins>
34         <!-- java编译插件 -->
35         <plugin>
36             <groupId>org.apache.maven.plugins</groupId>
37             <artifactId>maven-compiler-plugin</artifactId>
38             <version>3.2</version>
39             <configuration>
40                 <source>1.7</source>
41                 <target>1.7</target>
42                 <encoding>UTF-8</encoding>
43             </configuration>
44         </plugin>
45     </plugins>
46 </build>

2.1.2、创建索引的流程分析

关于Lucene全文检索相关技术第4张

2.1.3、创建索引的代码实现

 1 /**
 2  * 创建索引
 3  * @throws Exception 
 4  */
 5 @Test
 6 public void testCreateIndex() throws Exception{
 7     // 创建文档对象
 8     Document document = new Document();
 9     // 添加字段,这里字段的参数:字段的名称、字段的值、是否存储。Store.YES存储,Store.NO是不存储
10     document.add(new StringField("id", "1", Store.YES));
11     // StringField会创建索引,但是不做分词,而TextField会创建索引并且分词
12     document.add(new TextField("title", "谷歌地图之父跳槽FaceBook", Store.YES));
13     
14     // 创建索引目录对象
15     Directory directory = FSDirectory.open(new File("indexDir"));
16     // 创建分词器对象
17     Analyzer analyzer = new StandardAnalyzer();
18     // 创建索引写出工具的配置类
19     IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, analyzer);
20     // 创建索引写出工具
21     IndexWriter writer = new IndexWriter(directory, conf);
22     
23     // 添加文档到索引写出工具
24     writer.addDocument(document);
25     // 提交
26     writer.commit();
27     // 关闭
28     writer.close();
29 }

关于Lucene全文检索相关技术第5张

2.2、使用工具查看创建好的索引

 关于Lucene全文检索相关技术第6张

关于Lucene全文检索相关技术第7张

关于Lucene全文检索相关技术第8张

2.3、创建索引的核心API

2.3.1、Document(文档类)

Document:代表的是文档列表中的一条原始数据。

关于Lucene全文检索相关技术第9张

2.3.2、Field(字段类)

Field:一个文档中可以有很多的字段,每一个字段都是一个Field类的对象。Field类有很多的子类,这些子类有不同的特性,分别对应文档中具备不同特性的字段。

关于Lucene全文检索相关技术第10张

Field子类特点:

   A:IntField、DoubleField、LongField、FloatField、StringField、TextField这几个子类他们一定会被创建索引。但是不一定会被存储。需要通过创建字段时的参数来指定:Stroe.YES代表存储,Store.NO代表不存储

  关于Lucene全文检索相关技术第11张

  B:StringField和TextField都会被创建索引,但是StringField不会被分词,而TextField会被分词

  关于Lucene全文检索相关技术第12张

  C:StoredField 一定会被存储,但是一定不会创建索引。

  关于Lucene全文检索相关技术第13张

  关于Lucene全文检索相关技术第14张

问题1:如何判断是否需要创建索引?

         如果需要根据某个字段进行搜索,那么这个字段就必须创建索引。不能用StoreField

问题2:如何判断是否需要存储呢?

         如果一个字段最终需要返回给用户看,那么就必须存储,如果不需要,你就不存储。

问题3:是否需要分词?

         是否需要分词的前提,就是字段要先需要创建索引。

         但是如果这个字段的内容是不可分割的整体,那么就不需要分词。比如:id

2.3.3、Directory(目录类)

Directory:代表的是索引库所在的目录

关于Lucene全文检索相关技术第15张

FSDirectory:把数据存储在硬盘,好处:数据比较安全。弊端:查询速度略慢

RAMDirectory:把数据存在内存:查询速度快,数据不安全

关于Lucene全文检索相关技术第16张

2.3.4、Analyzer(分词器类)

2.3.4.1、分词器的种类:

 关于Lucene全文检索相关技术第17张

Analyzer有非常多的子类,支持大部分国家的语言,但是对中文的支持非常差。

所以,我们一旦要做中文分词,就要用中文分词器。

专业的中文分词器,有以下这些:

 关于Lucene全文检索相关技术第18张

2.3.4.2、IKAnalyzer分词器使用:

  IKAnalyzer(中文分词器)

   关于Lucene全文检索相关技术第19张

  IK分词器官方版本是不支持Lucene4.X的,有人基于IK的源码做了改造,支持了Lucene4.X

  关于Lucene全文检索相关技术第20张

2.3.4.3、IKAnalyzer的使用

添加依赖

关于Lucene全文检索相关技术第21张

关于Lucene全文检索相关技术第22张

关于Lucene全文检索相关技术第23张

一些后来出现的新词,在IK分词器中,是没有的。因此IK分词器提供了扩展词库和停止词库

  扩展词库:我们自己指定一些自定义的词条。

  停止词库:某些不需要做分词的内容。啊、哦、的、额

关于Lucene全文检索相关技术第24张

关于Lucene全文检索相关技术第25张

关于Lucene全文检索相关技术第26张

关于Lucene全文检索相关技术第27张

关于Lucene全文检索相关技术第28张

2.3.4.4、IndexWriterConfig(写出配置类)

IndexWriterConfig:用来设置写出工具的配置信息。在构造函数中,指定版本号和分词器对象

 关于Lucene全文检索相关技术第29张

设置创建索引时是追加还是覆盖:

 关于Lucene全文检索相关技术第30张

2.3.4.5、IndexWriter(索引写出类)

1)一次创建一个索引

 关于Lucene全文检索相关技术第31张

IndexWriter的作用:就是实现对索引库的更新操作:增(创建索引)、删(删除索引)、改(修改索引)

2)一次创建多个索引

 1 /**
 2  * 批量创建索引
 3  * @throws Exception 
 4  */
 5 @Test
 6 public void testCreateIndexes() throws Exception{
 7     // 创建文档的集合
 8     Collection<Document> docs = new ArrayList<>();
 9     // 创建文档对象
10     Document document1 = new Document();
11     document1.add(new StringField("id", "1", Store.YES));
12     document1.add(new TextField("title", "谷歌地图之父跳槽FaceBook", Store.YES));
13     docs.add(document1);
14     Document document2 = new Document();
15     document2.add(new StringField("id", "2", Store.YES));
16     document2.add(new TextField("title", "谷歌地图之父加盟FaceBook", Store.YES));
17     docs.add(document2);
18     Document document3 = new Document();
19     document3.add(new StringField("id", "3", Store.YES));
20     document3.add(new TextField("title", "谷歌地图创始人拉斯离开谷歌加盟Facebook", Store.YES));
21     docs.add(document3);
22     Document document4 = new Document();
23     document4.add(new StringField("id", "4", Store.YES));
24     document4.add(new TextField("title", "谷歌地图之父跳槽Facebook与Wave项目取消有关", Store.YES));
25     docs.add(document4);
26     Document document5 = new Document();
27     document5.add(new StringField("id", "5", Store.YES));
28     document5.add(new TextField("title", "谷歌地图之父跳槽Facebook与Wave项目取消有关", Store.YES));
29     docs.add(document5);
30     
31     // 创建索引目录对象
32     Directory directory = FSDirectory.open(new File("indexDir"));
33     // 创建分词器对象
34     Analyzer analyzer = new IKAnalyzer();
35     
36     // 创建索引写出工具的配置类
37     IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, analyzer);
38     // 设置打开方式:默认是OpenMode.APPEND,代表每次添加索引都追加到末尾;OpenMode.CREATE代表先清空索引,再添加
39     conf.setOpenMode(OpenMode.CREATE);
40     // 创建索引写出工具
41     IndexWriter writer = new IndexWriter(directory, conf);
42     
43     // 添加文档集合 到索引写出工具
44     writer.addDocuments(docs);
45     // 提交
46     writer.commit();
47     // 关闭
48     writer.close();
49 }

2.4、使用Lucene搜索索引库数据

 1 @Test
 2 public void testSearch() throws Exception{
 3     // 创建索引目录对象
 4     Directory directory = FSDirectory.open(new File("indexDir"));
 5     // 创建索引读取工具
 6     IndexReader reader = DirectoryReader.open(directory);
 7     // 索引的搜索工具类
 8     IndexSearcher searcher = new IndexSearcher(reader);
 9     
10     // 创建查询解析器对象。参数:默认查询的字段名称,分词器对象
11     QueryParser parser = new QueryParser("title", new IKAnalyzer());
12     // 创建查询对象
13     Query query = parser.parse("跳槽");
14     // 执行Query对象,搜索数据。参数:查询对象Query,查询结果的前N条数据
15     // 返回的是:相关度最高的前N名的文档信息(包含文档的编号以及查询到的总数量)
16     TopDocs topDocs = searcher.search(query, 10);
17     
18     System.out.println("本次共搜索到"+topDocs.totalHits+"条数据");
19     // 获取ScoreDoc(包含编号及得分) 数组
20     ScoreDoc[] scoreDocs = topDocs.scoreDocs;
21     // 遍历
22     for (ScoreDoc scoreDoc : scoreDocs) {
23         // 获取一个文档的编号
24         int docID = scoreDoc.doc;
25         // 根据编号获取文档
26         Document document = reader.document(docID);
27         System.out.println("id: " + document.get("id"));
28         System.out.println("title: " + document.get("title"));
29         // 打印得分
30         System.out.println("得分: " + scoreDoc.score);
31     }
32 }

2.5、搜索索引库的核心API

2.5.1、QueryParser(查询解析器)

QueryParser:可以解析用户输入的字段,获取查询对象(单一字段的查询解析器)

关于Lucene全文检索相关技术第32张

MultiFieldQueryParser(多字段组合查询解析器)

 关于Lucene全文检索相关技术第33张

2.5.2、Query(查询类)

1)解析关键词,获取查询对象

 关于Lucene全文检索相关技术第34张

2)通过Query子类创建特殊查询对象

 关于Lucene全文检索相关技术第35张

2.5.3、IndexSearch(索引搜索类)

IndexSearch:可以帮我们实现 搜索索引库,获取数据。还可以实现很多高级搜索功能

关于Lucene全文检索相关技术第36张

关于Lucene全文检索相关技术第37张

2.5.4、TopDocs(搜索结果的信息集合)

TopDocs:相关度最高的前N名的文档信息,N可以通过搜索时的参数指定

这个文档信息包含两部分:

         int totalHits:查询到的总数量

         ScoreDoc[] scoreDocs:ScoreDoc的数组,ScoreDoc里就有文档的编号

关于Lucene全文检索相关技术第38张

2.5.5、ScoreDoc(搜索到的某个文档信息)

ScoreDoc:包含了文档的编号和得分信息

         int doc:文档的编号,我们还需要根据文档编号获取具体的文档

         int score:文档的得分

关于Lucene全文检索相关技术第39张

2.6、抽取公共的搜索方法

 1 // 公共的搜索方法。
 2 public void search(Query query) throws Exception {
 3     // 创建索引目录对象、
 4     Directory directory = FSDirectory.open(new File("indexDir"));
 5     // 创建索引读取工具
 6     IndexReader reader = DirectoryReader.open(directory);
 7     // 创建搜索工具
 8     IndexSearcher searcher = new IndexSearcher(reader);
 9 
10     // 执行查询,获取前N名的 文档信息
11     TopDocs topDocs = searcher.search(query, 10);
12 
13     // 获取总条数
14     int totalHits = topDocs.totalHits;
15     System.out.println("本次搜索共" + totalHits + "条数据");
16     
17     // 获取ScoreDoc(文档的得分及编号)的数组
18     ScoreDoc[] scoreDocs = topDocs.scoreDocs;
19     for (ScoreDoc scoreDoc : scoreDocs) {
20         // 获取编号
21         int docID = scoreDoc.doc;
22         // 根据编号找文档
23         Document document = reader.document(docID);
24         System.out.println("id: " + document.get("id"));
25         System.out.println("title: " + document.get("title"));
26         // 获取得分
27         System.out.println("得分:" + scoreDoc.score);
28     }
29 }

2.7、特殊查询

2.7.1、TermQuery(词条查询)

关于Lucene全文检索相关技术第40张

关于Lucene全文检索相关技术第41张

2.7.2、WildcardQuery(模糊查询)

 关于Lucene全文检索相关技术第42张

关于Lucene全文检索相关技术第43张

2.7.3、FuzzyQuery(相似度查询)

 关于Lucene全文检索相关技术第44张

2.7.4、NumericRangeQuery(数字边界查询)

关于Lucene全文检索相关技术第45张

2.7.8、BooleanQuery(组合查询)

关于Lucene全文检索相关技术第46张

2.8、使用Lucene修改索引

 1 /*
 2  * 演示:修改索引。
 3  * 一般情况下,我们修改索引,一定是要精确修改某一个,因此一般会根据ID字段进行修改。
 4  * 但是在Lucene中,词条查询要求字段必须是字符串类型,所以,我们的ID也必须是字符串
 5  * 如果ID为数值类型,要修改一个指定ID的文档。我们可以先删除,再添加。
 6  */
 7 @Test
 8 public void testUpdate() throws Exception{
 9     // 创建目录
10     Directory directory = FSDirectory.open(new File("indexDir"));
11     // 创建配置对象
12     IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
13     // 创建索引写出类
14     IndexWriter writer = new IndexWriter(directory, conf);
15     
16     // 创建新的文档对象
17     Document doc = new Document();
18     doc.add(new StringField("id","1",Store.YES));
19     doc.add(new TextField("title", "谷歌地图之父跳槽FaceBook 加入传智播客 屌爆了", Store.YES));
20     
21     // 修改文档,两个参数:一个词条,通过词条精确匹配一个要修改的文档;要修改的新的文档数据
22     writer.updateDocument(new Term("id","1"), doc);
23     // 提交
24     writer.commit();
25     // 关闭
26     writer.close();
27 }

数据已经改变:

关于Lucene全文检索相关技术第47张

2.9、使用Lucene删除索引

 1 /*
 2  * 演示:删除索引。
 3  * 1)一次删除一个:
 4  *     一般情况下,我们删除索引,一定是要精确删除某一个,因此一般会根据ID字段进行删除。
 5  *     但是在Lucene中,词条查询要求字段必须是字符串类型,所以,我们的ID也必须是字符串
 6  * 2)删除所有
 7  *     deleteAll()
 8  */
 9 @Test
10 public void testDelete() throws Exception{
11     // 创建目录
12     Directory directory = FSDirectory.open(new File("indexDir"));
13     // 创建配置对象
14     IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
15     // 创建索引写出类
16     IndexWriter writer = new IndexWriter(directory, conf);
17     
18     // 根据词条删除索引,一次删1条,要求ID必须是字符串
19     // writer.deleteDocuments(new Term("id", "1"));
20     
21     // 如果ID为数值类型,那么无法根据Term删除,那么怎么办?
22     
23     // 根据Query删除索引,我们用NumericRangeQuery精确锁定一条 指定ID的文档
24     Query query = NumericRangeQuery.newLongRange("id", 2L, 2L, true, true);
25     writer.deleteDocuments(query);
26     
27     // 删除所有
28     writer.deleteAll();
29     
30     // 提交
31     writer.commit();
32     // 关闭
33     writer.close();
34 }
3、Lucene高级使用

3.1、Lucene实现关键词高亮显示

高亮显示的原理:

  1)在返回的结果中,给所有关键字前后,添加一个自定义的HTML标签

        关于Lucene全文检索相关技术第48张

  2)给这个标签设置CSS样式

  关于Lucene全文检索相关技术第49张

 1 /*
 2  * 演示:Lucene实现高亮
 3  */
 4 @Test
 5 public void testHighlighter() throws Exception {
 6     // 创建索引目录对象、
 7     Directory directory = FSDirectory.open(new File("indexDir"));
 8     // 创建索引读取工具
 9     IndexReader reader = DirectoryReader.open(directory);
10     // 创建搜索工具
11     IndexSearcher searcher = new IndexSearcher(reader);
12     
13     // 查询解析器
14     QueryParser parser = new QueryParser("title", new IKAnalyzer());
15     Query query = parser.parse("谷歌地图");
16     
17     // 创建格式化工具
18     Formatter formatter = new SimpleHTMLFormatter("<em>", "</em>");
19     Scorer scorer = new QueryScorer(query);
20     // 创建高亮显示的工具
21     Highlighter highlighter = new Highlighter(formatter, scorer);
22     
23     // 执行查询,获取前N名的 文档信息
24     TopDocs topDocs = searcher.search(query, 10);
25     // 获取总条数
26     int totalHits = topDocs.totalHits;
27     System.out.println("本次搜索共" + totalHits + "条数据");
28     // 获取ScoreDoc(文档的得分及编号)的数组
29     ScoreDoc[] scoreDocs = topDocs.scoreDocs;
30     for (ScoreDoc scoreDoc : scoreDocs) {
31         // 获取编号
32         int docID = scoreDoc.doc;
33         // 根据编号找文档
34         Document document = reader.document(docID);
35         System.out.println("id: " + document.get("id"));
36         
37         // 获取原始结果
38         String title = document.get("title");
39         // 使用高亮工具把原始结果变成高亮结果:三个参数:分词器,要高亮的字段名称,原始结果
40         String highTitle = highlighter.getBestFragment(new IKAnalyzer(), "title", title); 
41         
42         System.out.println("title: " + highTitle);
43         // 获取得分
44         System.out.println("得分:" + scoreDoc.score);
45     }
46 }

3.2、使用Lucene实现排序

 1 /*
 2  * 演示:Lucene实现排序
 3  */
 4 @Test
 5 public void testSort() throws Exception {
 6     // 创建索引目录对象、
 7     Directory directory = FSDirectory.open(new File("indexDir"));
 8     // 创建索引读取工具
 9     IndexReader reader = DirectoryReader.open(directory);
10     // 创建搜索工具
11     IndexSearcher searcher = new IndexSearcher(reader);
12     // 查询解析器
13     QueryParser parser = new QueryParser("title", new IKAnalyzer());
14     Query query = parser.parse("谷歌地图");
15     
16     // 创建排序的对象,然后接收排序的字段。参数:字段名称,字段类型,是否反转。false升序,true降序
17     Sort sort = new Sort(new SortField("id", Type.LONG, true));
18     // 执行查询,获取前N名的 文档信息
19     TopDocs topDocs = searcher.search(query, 10, sort);
20     
21     // 获取总条数
22     int totalHits = topDocs.totalHits;
23     System.out.println("本次搜索共" + totalHits + "条数据");
24     // 获取ScoreDoc(文档的得分及编号)的数组
25     ScoreDoc[] scoreDocs = topDocs.scoreDocs;
26     for (ScoreDoc scoreDoc : scoreDocs) {
27         // 获取编号
28         int docID = scoreDoc.doc;
29         // 根据编号找文档
30         Document document = reader.document(docID);
31         System.out.println("id: " + document.get("id"));
32         System.out.println("title: " + document.get("title"));
33     }
34 }

3.3、使用Lucene实现分页查询

 1 /*
 2  * 演示:Lucene实现分页查询 Lucene本身不提供分页功能。因此,要实现分页,我们必须自己来完成。也就是逻辑分页
 3  * 先查询全部,然后返回需要的那一页数据。
 4  */
 5 @Test
 6 public void testPageQuery() throws Exception {
 7     // 准备分页参数:
 8     int pageSize = 5;// 每页条数
 9     int pageNum = 2;// 当前页
10     int start = (pageNum - 1) * pageSize;// 起始角标
11     int end = start + pageSize;// 结束角标
12 
13     // 创建索引目录对象、
14     Directory directory = FSDirectory.open(new File("indexDir"));
15     // 创建索引读取工具
16     IndexReader reader = DirectoryReader.open(directory);
17     // 创建搜索工具
18     IndexSearcher searcher = new IndexSearcher(reader);
19     // 查询解析器
20     QueryParser parser = new QueryParser("title", new IKAnalyzer());
21     Query query = parser.parse("谷歌");
22     // 创建排序的对象,然后接收排序的字段。参数:字段名称,字段类型,是否反转。false升序,true降序
23     Sort sort = new Sort(new SortField("id", Type.LONG, false));
24     // 执行查询,获取的是0~end之间的数据
25     TopDocs topDocs = searcher.search(query, end, sort);
26 
27     // 获取总条数
28     int totalHits = topDocs.totalHits;
29     // 获取总页数
30     int totalPages = (totalHits + pageSize - 1) / pageSize;
31 
32     System.out.println("本次搜索共" + totalHits + "条数据,共" + totalPages + "页,当前是第" + pageNum + "页");
33     // 获取ScoreDoc(文档的得分及编号)的数组
34     ScoreDoc[] scoreDocs = topDocs.scoreDocs;
35     for (int i = start; i < end; i++) {
36         ScoreDoc scoreDoc = scoreDocs[i];
37         // 获取编号
38         int docID = scoreDoc.doc;
39         // 根据编号找文档
40         Document document = reader.document(docID);
41         System.out.println("id: " + document.get("id"));
42         System.out.println("title: " + document.get("title"));
43     }
44 }

3.4、使用Lucene得分计算

 Lucene会对搜索结果打分,用来表示文档数据与词条关联性的强弱,得分越高,表示查询的匹配度就越高,排名就越靠前!其算法公式是:

 关于Lucene全文检索相关技术第50张

关于Lucene全文检索相关技术第51张

关于Lucene全文检索相关技术第52张

免责声明:文章转载自《关于Lucene全文检索相关技术》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇网站日志流量分析系统之离线分析(自动化脚本)EcShop二次开发系列教程–总纲下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

R语言自然语言处理:关键词提取(TF-IDF)

作者:黄天元,复旦大学博士在读,热爱数据科学与开源工具(R/Python),致力于利用数据科学迅速积累行业经验优势和科学知识发现,涉猎内容包括但不限于信息计量、机器学习、数据可视化、应用统计建模、知识图谱等,著有《R语言高效数据处理指南》、《文本数据挖掘——基于R语言》(《文本数据挖掘 基于R语言》(黄天元)【摘要 书评 试读】- 京东图书)。知乎专栏:R...

如何设计实时数据平台(技术篇)

  敏捷之歌 我抽数故我存在 | DBus 人人玩转流处理 | Wormhole 就当吾是数据库 | Moonbox 颜值最后十公里 | Davinci 导读:实时数据平台(RTDP,Real-time Data Platform)是一个重要且常见的大数据基础设施平台。在上篇(设计篇)中,我们从现代数仓架构角度和典型数据处理角度介绍了RTDP,并探讨了...

OHC Java堆外缓存详解与应用

1、背景   在当前微服务体系架构中,有很多服务例如,在 特征组装 与 排序等场景都需要有大量的数据支撑,快速读取这些数据对提升整个服务于的性能起着至关重要的作用。   缓存在各大系统中应用非常广泛。尤其是业务程序所依赖的数据可能在各种类型的数据库上(mysql、hive 等),那么如果想要获取到这些数据需要通过网络来访问。再加上往往数据量又很庞大,网络传...

三种存储类型比较-文件、块、对象存储

块存储和文件存储是我们比较熟悉的两种主流的存储类型,而对象存储(Object-based Storage)是一种新的网络存储架构,基于对象存储技术的设备就是对象存储设备(Object-based Storage Device)简称OSD。 首先,我们介绍这两种传统的存储类型。通常来讲,所有磁盘阵列都是基于Block块的模式,而所有的NAS产品都是文件级存储...

windows server常用命令

ARP -A 获取与本机通讯过(20分钟内)的主机MAC地址和IP地址 tracert 路由追踪 DOS下IP 获取MAC地址 nbtstat -a IP nslookup 查询DNS解析 ipconfig /flushdns 刷新DNS解析 ipconfig /release 手动释放IP地址 ipconfig /renew 手动更新IP地址 mstsc...

ceph介绍

  一、Ceph简介:         Ceph是一种为优秀的性能、可靠性和可扩展性而设计的统一的、分布式文件系统。ceph 的统一体现在可以提供文件系统、块存储和对象存储,分布式体现在可以动态扩展。在国内一些公司的云环境中,通常会采用 ceph 作为openstack 的唯一后端存储来提高数据转发效率。        Ceph项目最早起源于Sage就读...