之前的博客搜索栏用的是 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. 机器学习基础系列--先验概率 后验概率 似然函数 最大似然估计(MLE) 最大后验概率(MAE) 以及贝叶斯公式的理解

    目录 机器学习基础 1. 概率和统计 2. 先验概率(由历史求因) 3. 后验概率(知果求因) 4. 似然函数(由因求果) 5. 有趣的野史--贝叶斯和似然之争-最大似然概率(MLE)-最大后验概率( ...

  2. 关于自学java的内容及感受

    这周自学了关于java输入的知识:java输入的方法与c++和c有些不同,他需要在开头加一个import连接系统的包,才能进行输入语句的编写. 自己编写了一点简单的输入的程序: package mod ...

  3. vue学习笔记:Hello Vue

    编写简单例子,了解下基本语法 <!DOCTYPE html> <html> <head> <meta charset="utf-8 "&g ...

  4. null值可以赋给引用变量,不能给基本类型

    下面正确的写法是? cbyte i=128 boolean i=null long i=0xfffL double i=0.9239d null表示没有地址:null可以赋值给引用变量,不能将null ...

  5. Redis 事务在 SpringBoot 中的应用 (io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI)

    我们在 SpringBoot 中使用 Redis 时,会引入如下的 redis starter <dependency> <groupId>org.springframewor ...

  6. Django问题 Did you rename .....a ForeignKey

    给新加入的字段添加一个default默认值即可,让字段非空.然后在进行makemigrations,完成操作后删除相关默认值即可.

  7. ch8 让div居中--使用外边距

    假设有一个布局,希望让其中的容器div在屏幕上水平居中,则只需要定义div的宽度,然后将水平外边距设置为auto <body> <div class="wrapper&qu ...

  8. Gamma 矫正

    参考如下链接: https://www.zhihu.com/question/27467127

  9. jdbc学习over

    这次的代码和之前学习到一般的代码主要就是将一些很常见的操作(建立连接.清除连接)不管做什么操作都需要用到它们,所以将它们单独放到另一个工具类里面去. 用到的术语: 1.事务:https://www.c ...

  10. 查漏补缺之slice

    interviewer:说一说slice interviewee: 主要包括以下几点 slice and array slice的底层数据结构 length和capacity 切片的capacity的 ...