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

一、Lucene检索的基本步骤

 import java.nio.file.Paths;
import java.io.*; import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version; /**
* @author csl
* @description:
* 依赖jar:Lucene-core,lucene-analyzers-common,lucene-queryparser
* 作用:使用索引搜索文件
*/
public class Searcher {
public static Version luceneVersion = Version.LATEST;
/**
* 查询内容
*/
public static String indexSearch(String keywords){
String res = "";
DirectoryReader reader = null;
try{
// 1、创建Directory
Directory directory = FSDirectory.open(Paths.get("index"));//在硬盘上生成Directory
// 2、创建IndexReader
reader = DirectoryReader.open(directory);
// 3、根据IndexReader创建IndexSearcher
IndexSearcher searcher = new IndexSearcher(reader);
// 4、创建搜索的query
// 创建parse用来确定搜索的内容,第二个参数表示搜索的域
QueryParser parser = new QueryParser("content",new StandardAnalyzer());//content表示搜索的域或者说字段
Query query = parser.parse(keywords);//被搜索的内容
// 5、根据Searcher返回TopDocs
TopDocs tds = searcher.search(query, 20);//查询20条记录
// 6、根据TopDocs获取ScoreDoc
ScoreDoc[] sds = tds.scoreDocs;
// 7、根据Searcher和ScoreDoc获取搜索到的document对象
int cou=0;
for(ScoreDoc sd:sds){
cou++;
Document d = searcher.doc(sd.doc);
// 8、根据document对象获取查询的字段值
/** 查询结果中content为空,是因为索引中没有存储content的内容,需要根据索引path和name从原文件中获取content**/
res+=cou+". "+d.get("path")+" "+d.get("name")+" "+d.get("content")+"\n";
} }catch(Exception e){
e.printStackTrace();
}finally{
//9、关闭reader
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return res;
}
public static void main(String[] args) throws IOException
{
System.out.println(indexSearch("你好")); //搜索的内容可以修改
}
}

Searcher

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

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

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

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

IndexReader

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

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

 IndexSearcher searcher =  new IndexSearcher(reader);

IndexSearcher

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

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

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

 QueryParser parser = new QueryParser("content",new StandardAnalyzer());//content表示搜索的域或者说字段
Query query = parser.parse(keywords);//被搜索的内容

QueryParser

解析分为两个过程:

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

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

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

Search

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

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

 int cou=0;
for(ScoreDoc sd:sds){
cou++;
Document d = searcher.doc(sd.doc);
// 8、根据document对象获取查询的字段值
/** 查询结果中content为空,是因为索引中没有存储content的内容,需要根据索引path和name从原文件中获取content**/
res+=cou+". "+d.get("path")+" "+d.get("name")+" "+d.get("content")+"\n";
}

Document

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

5.1 给关键词标注高亮。

     public  static String displayHtmlHighlight(Query query, String fieldName, String fieldContent) throws IOException, InvalidTokenOffsetsException
{
MyIkAnalyzer analyzer=new MyIkAnalyzer();
//设置高亮标签,可以自定义
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='#ff0000'>", "</font>");
/**创建QueryScorer*/
//评分
QueryScorer scorer=new QueryScorer(query);
/**创建Fragmenter*/
Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
//高亮分析器
Highlighter highlight=new Highlighter(formatter,scorer);
highlight.setTextFragmenter(fragmenter);
//fieldname是域名,如"title",fieldContent是d.get("title");
String str=highlight.getBestFragment(analyzer, fieldName, fieldContent);
if (str==null) return fieldContent;
return str;
}

displayHtmlHighlight

该函数有三个参数:

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

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

  • 如果要标注内容fieldContent为空,返回空串。
  • 不为空时,对fieldContent进行自定义的html标签标注。
 SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='#ff0000'>", "</font>");  

formatter

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

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

5.2 分页展示结果。

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

 int start=(pageIndex-1)*pageSize;
int end=pageIndex*pageSize;
Document d=null;
int cnt=0;
for(int i=start;i<end&&i<sds.length;i++)
{
d = searcher.doc(sds[i].doc);
//输出d
}

分页

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

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

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

3.6 Lucene基本检索+关键词高亮+分页的更多相关文章

  1. Lucene 05 - 使用Lucene的Java API实现分页查询

    目录 1 Lucene的分页查询 2 代码示例 3 分页查询结果 1 Lucene的分页查询 搜索内容过多时, 需要考虑分页显示, 像这样: 说明: Lucene的分页查询是在内存中实现的. 2 代码 ...

  2. 和我一起打造个简单搜索之SpringDataElasticSearch关键词高亮

    前面几篇文章详细讲解了 ElasticSearch 的搭建以及使用 SpringDataElasticSearch 来完成搜索查询,但是搜索一般都会有搜索关键字高亮的功能,今天我们把它给加上. 系列文 ...

  3. php-设置关键词高亮的字符串处理函数

    /** * 设置关键词高亮的字符串处理函数 * @param [string] $str [要高亮的字符串] * @param array $word_arr [关键词] */function set ...

  4. jQuery实现页面关键词高亮

    示例代码,关键位置做了注释,请查看代码: <html> <head> <title>jQuery实现页面关键词高亮</title> <style ...

  5. 微信小程序--搜索关键词高亮

    代码地址如下:http://www.demodashi.com/demo/14249.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.co ...

  6. lucene查询索引库、分页、过滤、排序、高亮

    2.查询索引库 插入测试数据 xx.xx. index. ArticleIndex @Test public void testCreateIndexBatch() throws Exception{ ...

  7. 2 Match、Filter、排序、分页、全文检索、短语匹配、关键词高亮

    查索引内所有文档记录 GET  /beauties/my/_search   GET  /beauties/my/_search {     "query":{         & ...

  8. Django Haystack 全文检索与关键词高亮

    Django Haystack 简介 django-haystack 是一个专门提供搜索功能的 django 第三方应用,它支持 Solr.Elasticsearch.Whoosh.Xapian 等多 ...

  9. 一个Solr搜索实例,增删改查+高亮+分页

    今天个人coding的模块测试,所以闲暇之余继续研究solr,然后顺带写了一个实例,随便搞的,solr真心不熟,期待认识热爱搜索的朋友,共同进步. 1.配置schema.xml文件[solr\coll ...

随机推荐

  1. oracle下表空间、用户创建以及用户授权流程

    Oracle,表空间的建立.用户创建以及用户授权 主要是以下几步,挑选需要的指令即可: # 首先以scott用户作为sysdba登陆 conn scott/tiger as sysdba #创建用户 ...

  2. php扩展开发-资源类型

    资源类型在内核中的结构 //zend_list.h typedef struct _zend_rsrc_list_entry { void *ptr; int type; int refcount; ...

  3. [Codeforces958C2]Encryption (medium)(区间DP)

    Description 题目链接 Solution 显然的区间DP,正常想法f[i][j]表示前i个数分成j块,每次在i前找一个k使得balala,然而常规打法会超时 我们发现,对于i前面的所有点,他 ...

  4. 2753: [SCOI2012]滑雪与时间胶囊

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 2633  Solved: 910 Descriptio ...

  5. Quartus 11生成pof文件在AS烧写之后,程序无法启动

    1. 首先配置成AS,生成.pof文件,选择上面的图标Device 2. 选择Device and Pin Options... 3. 进入配置界面,选择如下 4. 进入下载界面,烧写.pof文件,开 ...

  6. Eclipse 窗口说明---Eclipse教程第03课

    Eclipse 工作台(Workbench) 首先,让我们来看一下Eclipse 作台用户界面,和它里面的各种组件. 工作台是多个窗口的集合.每个窗口包含菜单栏,工具栏,快捷方式栏,以及一个或者多个透 ...

  7. linux下给开启端口

    首先在这里要推荐一篇博文 http://blog.csdn.net/zht666/article/details/17505789 这篇文章写的很详细,里面包含了操作端口一些命令,我们操作端口其实就是 ...

  8. Space Shooter 太空射击

    1.控制玩家移动 public float speed = 10f; public float xMin = -6.5f; public float xMax = 6.5f; public float ...

  9. python中的字符问题

    unicode/unicodebig/utf8 在python上默认情况下都解析不了 window系统中 ASCLL对应的是GBK unicode|unicodebigendian 对应 utf-16 ...

  10. 指定user镜像安装的磁盘

    ironic node-update <node uuid> add properties/root_device='{"name":"/dev/sdb&qu ...