之前的博客搜索栏用的是 sql 模糊查询进行查找,最近学完lucene,要学以致用啊,就把sql搜索给替换下来吧

  中间遇到一些问题,也是学过程中没有提到的,所以说,还是实践出真知啊。

lucene分开来讲的话,我感觉就是两大块:索引维护、搜索索引

索引维护包括:添加索引、删除索引、更新索引

public class BlogIndex {
// lucene 路径在 bean 里面配置
private String lucenePath;public String getLucenePath() {
return lucenePath;
} public void setLucenePath(String lucenePath) {
this.lucenePath = lucenePath;
} /**
* 获取对lucene的写入方法
*/
private IndexWriter getWriter() throws Exception {
Directory dir = FSDirectory.open(new File(lucenePath).toPath());
IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
IndexWriter indexWriter = new IndexWriter(dir,config);
return indexWriter;
} /**
* 增加索引
*/
public void addIndex(BlogCustom blog) throws Exception {
IndexWriter indexWriter = getWriter();
Document doc = new Document(); doc.add(new StringField("id",String.valueOf(blog.getId()),Field.Store.YES));
doc.add(new TextField("title",blog.getTitle(),Field.Store.YES));
doc.add(new TextField("summary",blog.getSummary(),Field.Store.YES));
doc.add(new TextField("keyWord",blog.getKeyWord(),Field.Store.YES));
indexWriter.addDocument(doc);
indexWriter.close();
} /**
* 更新索引
*/
public void updateIndex(BlogCustom blog) throws Exception {
IndexWriter indexWriter = getWriter();
Document doc = new Document(); doc.add(new StringField("id",blog.getId()+"",Field.Store.YES));
doc.add(new TextField("title",blog.getTitle(),Field.Store.YES));
doc.add(new TextField("summary",blog.getSummary(),Field.Store.YES));
doc.add(new TextField("keyWord",blog.getKeyWord(),Field.Store.YES)); indexWriter.updateDocument(new Term("id",String.valueOf(blog.getId())),doc);
indexWriter.close();
} /**
* 删除索引
*/
public void deleteIndex(String blogId) throws Exception {
IndexWriter indexWriter = getWriter();
indexWriter.deleteDocuments(new Term("id",blogId));
indexWriter.close();
}

搜索索引就比较复杂一点

    /**
* 搜索索引
*/
public List<BlogCustom> searchBlog(String q) throws Exception{
//创建一个 Analyzer对象,IKAnalyzer 对象
Analyzer analyzer = new IKAnalyzer();
List<BlogCustom> blogList = new LinkedList<>();
Directory dir = FSDirectory.open(new File(lucenePath).toPath());
IndexReader indexReader = DirectoryReader.open(dir);
IndexSearcher indexSearch = new IndexSearcher(indexReader); // 多域查询
String[] fields = {"id","title","summary","keyWord"};
// 表示多个条件之间的关系,SHOULD 只要一个域里面有满足我们的搜索的内容就行
// 数组长度 = fields 长度
BooleanClause.Occur[] clauses = { BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD,
BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD };
// 参数: 关键词、多域、条件之间的关系、中文分析器
Query query = MultiFieldQueryParser.parse(q, fields, clauses, analyzer);
// 查询结果,设置最多返回100条数据
TopDocs topDocs = indexSearch.search(query, 100); // 高亮关键词
// 高亮格式
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font style='color:red;'>","</font>");
// 关键词查询出来的指定位置
QueryScorer scorer = new QueryScorer(query);
// 在关键词指定位置,加上设定的高亮格式
Highlighter highlighter = new Highlighter(formatter,scorer);
// 设置含有关键字文本块的大小
highlighter.setTextFragmenter(new SimpleSpanFragmenter(scorer)); ScoreDoc[] scoreDocs = topDocs.scoreDocs;
//遍历查询结果,放入blogList
for(ScoreDoc scoreDoc : scoreDocs){
// 取当前文档
Document doc = indexSearch.doc(scoreDoc.doc);
BlogCustom blog = new BlogCustom(); // 取出关键词
int id = Integer.parseInt(doc.get("id"));
blog.setId(id);
String title = doc.get("title");
String summary = doc.get("summary");
String keyWord = doc.get("keyWord"); // 给不为空的关键词,加上高亮显示
if(title!=null) {
TokenStream tokenStream = analyzer.tokenStream("title", title);
String hTitle = highlighter.getBestFragment(tokenStream, title);
if(StringUtil.isEmpty(hTitle)) {
blog.setTitle(title);
}else {
blog.setTitle(hTitle);
}
}
if(summary!=null) {
TokenStream tokenStream = analyzer.tokenStream("summary", summary);
String hSummary = highlighter.getBestFragment(tokenStream, summary);
if(StringUtil.isEmpty(hSummary)) {
blog.setSummary(summary);
}else {
blog.setSummary(hSummary);
}
}
if(keyWord!=null) {
TokenStream tokenStream = analyzer.tokenStream("keyWord", keyWord);
String hKeyWord = highlighter.getBestFragment(tokenStream, keyWord);
if(StringUtil.isEmpty(hKeyWord)) {
blog.setKeyWord(keyWord);
}else {
blog.setKeyWord(hKeyWord);
}
}
blogList.add(blog);
}
return blogList;
} }

完成 !

lucene实践 - 索引维护、多域查询、高亮显示的更多相关文章

  1. [Elasticsearch] 多字段搜索 (六) - 自定义_all字段,跨域查询及精确值字段

    自定义_all字段 在元数据:_all字段中,我们解释了特殊的_all字段会将其它所有字段中的值作为一个大字符串进行索引.尽管将所有字段的值作为一个字段进行索引并不是非常灵活.如果有一个自定义的_al ...

  2. Lucene 的 Field 域和索引维护

    一.Field 域 1.Field 属性 Field 是文档中的域,包括 Field 名和 Field 值两部分,一个文档可以包括多个 Field,Document 只是 Field 的一个承载体,F ...

  3. Lucene实现索引和查询

    0引言 随着万维网的发展和大数据时代的到来,每天都有大量的数字化信息在生产.存储.传递和转化,如何从大量的信息中以一定的方式找到满足自己需求的信息,使之有序化并加以利用成为一大难题.全文检索技术是现如 ...

  4. lucene&solr学习——索引维护

    1.索引库的维护 索引库删除 (1) 全删除 第一步:先对文档进行分析 public IndexWriter getIndexWriter() throws Exception { // 第一步:创建 ...

  5. lucene查询索引之Query子类查询——(七)

    0.文档名字:(根据名字索引查询文档)

  6. Lucene之索引库的维护:添加,删除,修改

    索引添加 Field域属性分类 添加文档的时候,我们文档当中包含多个域,那么域的类型是我们自定义的,上个案例使用的TextField域,那么这个域他会自动分词,然后存储 我们要根据数据类型和数据的用途 ...

  7. 一步一步跟我学习lucene(18)---lucene索引时join和查询时join使用演示样例

    了解sql的朋友都知道,我们在查询的时候能够採用join查询,即对有一定关联关系的对象进行联合查询来对多维的数据进行整理.这个联合查询的方式挺方便的.跟我们现实生活中的托人找关系类似,我们想要完毕一件 ...

  8. 01 lucene基础 北风网项目培训 Lucene实践课程 索引

    在创建索引的过程中IndexWriter会创建多个对应的Segment,这个Segment就是对应一个实体的索引段.随着索引的创建,Segment会慢慢的变大.为了提高索引的效率,IndexWrite ...

  9. SolrJ 复杂查询 高亮显示

    SolrJ 复杂查询 高亮显示 上一章搭建了Solr服务器和导入了商品数据,本章通过SolrJ去学习Solr在企业中的运用.笔者最先是通过公司的云客服系统接触的Solr,几百万的留言秒秒钟就查询并高亮 ...

随机推荐

  1. 1.ORM介绍,基本配置及通过ORM框架创建表

    1.介绍 ORM全拼Object-Relation Mapping(对象-关系映射) 作用:主要实现模型对象到关系数据库数据的映射 通过ORM框架作为一个中间者或者是一个桥梁,开发者通过定义模型类,属 ...

  2. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:移除默认的列表样式

    <!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...

  3. C语言入门---第七章 C语言函数

    函数就是一段封装好的,可以重复使用的代码,它使得我们的程序更加模块化,不需要编写大量重复的代码.函数可以提前保存起来,并给它起一个独一无二的名字,只要知道它的名字就能使用这段代码.函数还可以接收数据, ...

  4. Fiddler抓包(基本使用方法、web+app端抓包、篡改数据、模拟低速)

    1.HTTP代理原理图 http服务器代理:既是web服务器,又是web客户端 接口vs端口: 接口:包含地址和端口 端口:类似于USB接口 地址:127.0.0.1,端口默认:8888        ...

  5. 阿里分布式开放消息服务(ONS)原理与实践——笔记整理

    1.MQ场景    1)订单异步解耦    2)解决分布式事务问题    3)应用于聊天平台    4)大规模机器的Cache同步    5)MySQL BinLog订阅数据分发2.ONS应用场景  ...

  6. FFmpeg——AVCodec,AVCodecContext,AVCodecParameters 辨析

    先贴上雷神的一张FFmpeg关键结构体之间的关系图: 再看雷神的分析: 每个AVStream存储一个视频/音频流的相关数据: 每个AVStream对应一个AVCodecContext,存储该视频/音频 ...

  7. 定位(left 、right 、top 、 bottom)、padding、margin 值设为百分比值时

    定位(left .right .top . bottom): top 为例 right 为例 padding.margin : 当padding.margin 值设为百分比值时,其百分比会相对于父元素 ...

  8. Ubuntu 编译 LAMP

    下载apache源码 http://httpd.apache.org/ 解压缩apache安装包,进入apache文件夹. 安装: apache2.2.9./configure --prefix=/u ...

  9. 4 ehcache 配置

    拷贝ehcache.xml文件到工程的resources目录下面 <?xml version="1.0" encoding="UTF-8"?> &l ...

  10. [Linux] day03——REHL部署

    REHL 部署 Linux 树形目录结构  最顶层 根 / 在Linux中 一切皆文件 文件系统 swap / 安装方式 PXE U盘 光盘 配置安装程序 选择包   5.9    6.4