zoukankan      html  css  js  c++  java
  • 3.6 Lucene基本检索+关键词高亮+分页

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

    一、Lucene检索的基本步骤

     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指向索引文件夹。

    1 Directory directory = FSDirectory.open(Paths.get("index"));
    2 IndexReader reader = DirectoryReader.open(directory);
    IndexReader

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

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

    1 IndexSearcher searcher =  new IndexSearcher(reader);
    IndexSearcher

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

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

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

    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。

    1 //            5、根据Searcher返回TopDocs
    2              TopDocs tds = searcher.search(query, 20);//查询20条记录
    3 //            6、根据TopDocs获取ScoreDoc
    4              ScoreDoc[] sds = tds.scoreDocs;
    Search

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

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

    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 给关键词标注高亮。

     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标签标注。
    1 SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='#ff0000'>", "</font>");  
    formatter

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

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

    5.2 分页展示结果。

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

    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的高级检索方式~~

  • 相关阅读:
    Scala学习(八)---Scala继承
    Scala学习(九)---文件和正则表达式
    Scala学习(六)---Scala对象
    jemter----命令行模式(cmd)导出测试报告
    js数据类型
    定期任务,如每月清理(SpringBoot Mybatis-Plus)
    定时执行任务(SpringBoot Mybatis-Plus)
    图片服务映射(SpringBoot mybatis-plus)
    图片压缩上传(Springboot mybatis-plus)
    java生成pdf
  • 原文地址:https://www.cnblogs.com/itcsl/p/6833046.html
Copyright © 2011-2022 走看看