3.6 Lucene基本检索+关键词高亮+分页

摘要:
1IndexSearchersarcher=newIndexSearcher;IndexSearcherIndexSearcher提供了两个非常重要的函数:void setSimilarity。用户可以实现自己的相似度对象,从而影响搜索过程的评分。一系列搜索功能是搜索过程的关键。他们主要负责评分的计算和倒表的合并。

3.2节我们已经运行了一个Lucene实现检索的小程序,这一节我们将以这个小程序为例,讲一下Lucene检索的基本步骤,同时介绍关键词高亮显示和分页返回结果这两个有用的技巧。

一、Lucene检索的基本步骤

3.6 Lucene基本检索+关键词高亮+分页第1张3.6 Lucene基本检索+关键词高亮+分页第2张
 1 import java.nio.file.Paths;
 2 import java.io.*;
 3 
 4 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 5 import org.apache.lucene.document.Document;
 6 import org.apache.lucene.index.DirectoryReader;
 7 import org.apache.lucene.queryparser.classic.QueryParser;
 8 import org.apache.lucene.search.IndexSearcher;
 9 import org.apache.lucene.search.Query;
10 import org.apache.lucene.search.ScoreDoc;
11 import org.apache.lucene.search.TopDocs;
12 import org.apache.lucene.store.Directory;
13 import org.apache.lucene.store.FSDirectory;
14 import org.apache.lucene.util.Version;
15 
16 /**
17  * @author csl
18  * @description: 
19  * 依赖jar:Lucene-core,lucene-analyzers-common,lucene-queryparser
20  * 作用:使用索引搜索文件
21  */
22 public class Searcher {
23     public static Version luceneVersion = Version.LATEST;
24     /**
25      * 查询内容
26      */
27     public static String indexSearch(String keywords){
28         String res = "";
29         DirectoryReader reader = null;
30         try{
31 //            1、创建Directory
32              Directory directory = FSDirectory.open(Paths.get("index"));//在硬盘上生成Directory
33 //            2、创建IndexReader
34              reader = DirectoryReader.open(directory);
35 //            3、根据IndexReader创建IndexSearcher
36              IndexSearcher searcher =  new IndexSearcher(reader);
37 //            4、创建搜索的query
38 //            创建parse用来确定搜索的内容,第二个参数表示搜索的域
39              QueryParser parser = new QueryParser("content",new StandardAnalyzer());//content表示搜索的域或者说字段
40              Query query = parser.parse(keywords);//被搜索的内容
41 //            5、根据Searcher返回TopDocs
42              TopDocs tds = searcher.search(query, 20);//查询20条记录
43 //            6、根据TopDocs获取ScoreDoc
44              ScoreDoc[] sds = tds.scoreDocs;
45 //            7、根据Searcher和ScoreDoc获取搜索到的document对象
46              int cou=0;
47              for(ScoreDoc sd:sds){
48                  cou++;
49                  Document d = searcher.doc(sd.doc);
50 //                    8、根据document对象获取查询的字段值
51                  /**  查询结果中content为空,是因为索引中没有存储content的内容,需要根据索引path和name从原文件中获取content**/
52                  res+=cou+". "+d.get("path")+" "+d.get("name")+" "+d.get("content")+"
";
53              }
54 
55             
56         }catch(Exception e){
57             e.printStackTrace();
58         }finally{
59             //9、关闭reader
60             try {
61                 reader.close();
62             } catch (IOException e) {
63                 e.printStackTrace();
64             }
65         }
66         return res;
67     }
68     public static void main(String[] args) throws IOException
69     {
70         System.out.println(indexSearch("你好")); //搜索的内容可以修改
71     }
72 }
Searcher

搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程。

总结起来检索有以下以下五个步骤:

1. 打开IndexReader指向索引文件夹。

3.6 Lucene基本检索+关键词高亮+分页第3张3.6 Lucene基本检索+关键词高亮+分页第4张
1 Directory directory = FSDirectory.open(Paths.get("index"));
2 IndexReader reader = DirectoryReader.open(directory);
IndexReader

这一步骤将磁盘上的索引信息读入内存。

2. 创建IndexSearcher准备进行搜索。

3.6 Lucene基本检索+关键词高亮+分页第5张3.6 Lucene基本检索+关键词高亮+分页第6张
1 IndexSearcher searcher =  new IndexSearcher(reader);
IndexSearcher

IndexSearcher提供了两个非常重要的函数:

  • void setSimilarity(Similarity similarity),用户可以实现自己的Similarity对象,从而影响搜索过程的打分。
  • 一系列search函数,是搜索过程的关键,主要负责打分的计算和倒排表的合并。

3. 创建QueryParser解析查询语句生成查询对象。

3.6 Lucene基本检索+关键词高亮+分页第7张3.6 Lucene基本检索+关键词高亮+分页第8张
1 QueryParser parser = new QueryParser("content",new StandardAnalyzer());//content表示搜索的域或者说字段
2 Query query = parser.parse(keywords);//被搜索的内容
QueryParser

解析分为两个过程:

  • 创建Analyer用来对查询语句进行词法分析和语言处理。
  • QueryParser调用parser进行语法分析,形成查询语法树,放到Query中。

4. IndexSearcher调用search对查询语法树Query进行搜索,得到结果集Topdocs。

3.6 Lucene基本检索+关键词高亮+分页第9张3.6 Lucene基本检索+关键词高亮+分页第10张
1 //            5、根据Searcher返回TopDocs
2              TopDocs tds = searcher.search(query, 20);//查询20条记录
3 //            6、根据TopDocs获取ScoreDoc
4              ScoreDoc[] sds = tds.scoreDocs;
Search

该方法收集文档集合并计算打分。

5. 返回查询结果给用户。

3.6 Lucene基本检索+关键词高亮+分页第11张3.6 Lucene基本检索+关键词高亮+分页第12张
1 int cou=0;
2              for(ScoreDoc sd:sds){
3                  cou++;
4                  Document d = searcher.doc(sd.doc);
5 //                    8、根据document对象获取查询的字段值
6                  /**  查询结果中content为空,是因为索引中没有存储content的内容,需要根据索引path和name从原文件中获取content**/
7                  res+=cou+". "+d.get("path")+" "+d.get("name")+" "+d.get("content")+"
";
8              }
Document

在返回查询结果给用户时,为了提高用户体验,我们可以给关键词标注高亮和分页返回结果。

5.1 给关键词标注高亮。

3.6 Lucene基本检索+关键词高亮+分页第13张3.6 Lucene基本检索+关键词高亮+分页第14张
 1     public  static String displayHtmlHighlight(Query query, String fieldName, String fieldContent) throws IOException, InvalidTokenOffsetsException
 2     {
 3          MyIkAnalyzer analyzer=new MyIkAnalyzer();
 4          //设置高亮标签,可以自定义
 5          SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='#ff0000'>", "</font>");  
 6          /**创建QueryScorer*/
 7          //评分
 8          QueryScorer scorer=new QueryScorer(query);  
 9          /**创建Fragmenter*/  
10          Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);  
11          //高亮分析器
12          Highlighter highlight=new Highlighter(formatter,scorer);  
13          highlight.setTextFragmenter(fragmenter);  
14          //fieldname是域名,如"title",fieldContent是d.get("title");
15          String str=highlight.getBestFragment(analyzer, fieldName, fieldContent);
16          if (str==null) return fieldContent;
17          return str;
18      }
displayHtmlHighlight

该函数有三个参数:

  • Query query是第4步产生的查询对象。
  • String fieldName是要标注内容的域名,比如“title”
  • String fieldContent是要标注的具体内容,比如某一个“title”的具体内容。

该函数实现了两个基本功能:

  • 如果要标注内容fieldContent为空,返回空串。
  • 不为空时,对fieldContent进行自定义的html标签标注。
3.6 Lucene基本检索+关键词高亮+分页第15张3.6 Lucene基本检索+关键词高亮+分页第16张
1 SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='#ff0000'>", "</font>");  
formatter

这里可以进行个性化定制。关于HighLighter的具体用法大家可以参考我的另一篇博客【lucene系列学习二】Lucene实现高亮显示关键词

关于关键词高亮的具体原理可以参考搜索结果的处理和显示《第六篇》

5.2 分页展示结果。

这里介绍一种简单的分页方法:

3.6 Lucene基本检索+关键词高亮+分页第17张3.6 Lucene基本检索+关键词高亮+分页第18张
1 int start=(pageIndex-1)*pageSize;
2 int end=pageIndex*pageSize;
3  Document d=null;
4  int cnt=0;
5  for(int i=start;i<end&&i<sds.length;i++)
6 {
7         d = searcher.doc(sds[i].doc);
8     //输出d
9 }     
分页

其中pageIndex和pageSize可以是前端传的参数。

以上五个步骤就可以基本实现Lucene的检索、关键词高亮和分页返回结果了,是不是很简单呢?

下节我们会介绍Lucene的高级检索方式~~

免责声明:文章转载自《3.6 Lucene基本检索+关键词高亮+分页》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Java基础知识强化之IO流笔记68:Properties和IO流集合使用docker-compose部署EFK下篇

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

相关文章

基于IKAnalyzer搭建分词服务

背景 前端高亮需要分词服务,nlp团队提供的分词服务需要跨域调用,而且后台数据索引使用的IK分词。综合评价,前端分词也需要基于IK分词器。IKAnalyzer服务已经停止更新,且对Lucene支持仅测试到4.x.x版本(6.x.x会出现异常),因此使用IK分词器时需要解决一些异常。 依赖 项目以及maven构建,需要指定IK依赖以及Lucene依赖如下:...

EncryptHelper加密对象-工具类

usingSystem; usingSystem.IO; usingSystem.Security.Cryptography; usingSystem.Text; usingSystem.Web.Security; namespaceCommon.Utility { /// <summary> ///Author...

vue JSON数据导出为 多个sheet表的excel文件

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />...

【转】Hive的insert操作

insert 语法格式为: 1. 基本的插入语法: insert overwrite table tablename [partition(partcol1=val1,partclo2=val2)] select_statement; insert into table tablename [partition(partcol1=val1,partclo2...

WebStorm设置左侧菜单栏背景和字体设置

WebStorm设置左侧菜单栏背景和字体设置  webstorm是一款前端IDE利器,个人感觉黑色的背景比较炫酷。第一步:点击"file --> settings",如下图所示:   第二步:选择appearance->Theme选择darcula(黑色主题)   在 IDE Settings > Appearance 的右边菜单里,选择...

DB2命令——客户端命令连接服务器

在DB2中从客户端访问服务器端的数据库时,不能直接用connect命令,而必须先建立通信node,再在node的基础上建立数据库连接。在命令行的具体操作如下: ->db2 catalog tcpip node ABC remote serverName server 50000 ->db2 catalog db databaseName at...