本篇博客记录使用Lucene的API来实现对索引的增(创建索引)、删(删除索引)、改(修改索引)、查(搜索数据),以完善我之前的记事本系统为例,直接上核心代码:

1、Lucene工具类

package com.ue.util;

import java.io.IOException;
import java.nio.file.Paths;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory;

/**
* @author LiJun
* @create 2019-07-02 18:23
*/
public class LuceneUtil {
/**
* 获取索引文件存放的文件夹对象
* @param path
* @return
*/
public static Directory getDirectory(String path) {
Directory directory = null;
try {
directory = FSDirectory.open(Paths.get(path));
} catch
(IOException e) {
e.printStackTrace();
}
return directory;
}

/**
* 索引文件存放在内存
* @return
*/
public static Directory getRAMDirectory() {
Directory directory = new RAMDirectory();
return directory;
}

/**
* 文件夹读取对象
* @param directory
* @return
*/
public static DirectoryReader getDirectoryReader(Directory directory) {
DirectoryReader reader = null;
try {
reader = DirectoryReader.open(directory);
} catch
(IOException e) {
e.printStackTrace();
}
return reader;
}

/**
* 文件索引对象
*
* @param reader
* @return
*/
public static IndexSearcher getIndexSearcher(DirectoryReader reader) {
IndexSearcher indexSearcher = new IndexSearcher(reader);
return indexSearcher;
}

/**
* 写入索引对象
*
* @param directory
* @param analyzer
* @return
*/
public static IndexWriter getIndexWriter(Directory directory, Analyzer analyzer) {
IndexWriter iwriter = null;
try {
IndexWriterConfig config = new IndexWriterConfig(analyzer);
config.setOpenMode(OpenMode.CREATE_OR_APPEND);

// Sort sort=new Sort(new SortField("content", Type.STRING));
// config.setIndexSort(sort);//排序
config.setCommitOnClose(true);
// 自动提交
// config.setMergeScheduler(new ConcurrentMergeScheduler());
// config.setIndexDeletionPolicy(new
// SnapshotDeletionPolicy(NoDeletionPolicy.INSTANCE));
iwriter = new IndexWriter(directory, config);
} catch
(IOException e) {
e.printStackTrace();
}
return iwriter;
}

/**
* 关闭索引文件生成对象以及文件夹对象
*
* @param indexWriter
* @param directory
*/
public static void close(IndexWriter indexWriter, Directory directory) {
if (indexWriter != null) {
try {
indexWriter.close();
} catch
(IOException e) {
indexWriter = null;
}
}

if (directory != null) {
try {
directory.close();
} catch
(IOException e) {
directory = null;
}
}
}

/**
* 关闭索引文件读取对象以及文件夹对象
*
* @param reader
* @param directory
*/
public static void close(DirectoryReader reader, Directory directory) {
if (reader != null) {
try {
reader.close();
} catch
(IOException e) {
reader = null;
}
}
if (directory != null) {
try {
directory.close();
} catch
(IOException e) {
directory = null;
}
}
}

/**
* 高亮标签
*
* @param query
* @param fieldName
* @return
*/

public static Highlighter getHighlighter(Query query, String fieldName) {
Formatter formatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>");
Scorer fragmentScorer = new QueryTermScorer(query, fieldName);
// QueryScorer fragmentScorer=new QueryScorer(query);
Highlighter highlighter = new Highlighter(formatter, fragmentScorer);
highlighter.setTextFragmenter(new SimpleFragmenter(200));
return highlighter;
}
}
2、对某一表进行索引操作的帮助类

package com.ue.component;

import com.ue.model.Diary;
import com.ue.service.DiaryService;
import com.ue.util.DateUtil;
import com.ue.util.LuceneUtil;
import com.ue.util.StringUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.store.Directory;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.StringReader;
import java.util.*;

import static com.ue.config.CommonConfig.INDEXPATH;

/**
* @author LiJun
* @create 2019-07-02 21:16
* 将所有的日记生成索引文件进行存储
*/
@Component
public class DiaryIndex {
@Autowired
private DiaryService diaryService;

/**
* 添加日记索引(发表日记的时候添加索引信息)
* @throws Exception
*/
public void addIndex(Diary diary) throws Exception {
Directory directory = LuceneUtil.getDirectory(INDEXPATH);
IndexWriter writer = LuceneUtil.getIndexWriter(directory, new SmartChineseAnalyzer());
Document doc = new Document();
doc.add(new StringField("did", String.valueOf(diary.getDid()), Field.Store.YES));
doc.add(new TextField("title", diary.getTitle(), Field.Store.YES));
doc.add(new StringField("releaseDate", DateUtil.formatDate(diary.getReleaseDate(), "yyyy-MM-dd"), Field.Store.YES));
doc.add(new TextField("content", StringUtils.html2Text(diary.getContent()), Field.Store.YES));
writer.addDocument(doc);
writer.close();
}

/**
* 删除指定日记的索引
* @param did
* @throws Exception
*/
public void deleteIndex(String did) throws Exception {
Directory directory = LuceneUtil.getDirectory(INDEXPATH);
IndexWriter writer = LuceneUtil.getIndexWriter(directory, new SmartChineseAnalyzer());
writer.deleteDocuments(new Term("did", did));
writer.forceMergeDeletes();//强制删除
writer.commit();
writer.close();
}

/**
* 更新日记索引
* @throws Exception
*/
public void updateIndex(Diary diary) throws Exception {
Directory directory = LuceneUtil.getDirectory(INDEXPATH);
IndexWriter writer = LuceneUtil.getIndexWriter(directory, new SmartChineseAnalyzer());
Document doc = new Document();
doc.add(new StringField("did", String.valueOf(diary.getDid()), Field.Store.YES));
doc.add(new TextField("title", diary.getTitle(), Field.Store.YES));
doc.add(new StringField("releaseDate", DateUtil.formatDate((Date) diary.getReleaseDate(), "yyyy-MM-dd"), Field.Store.YES));
doc.add(new TextField("content", StringUtils.html2Text(diary.getContent()), Field.Store.YES));
writer.updateDocument(new Term("did", String.valueOf(diary.getDid())), doc);
writer.close();
}

/**
* 将数据库中所有的日记进行索引,然后存储索引文件到指定的位置
* 当索引文件丢失的时候使用
*/
public void indexDiarys() throws Exception {
System.out.println("-------------------------开始生成索引-------------------------");
File file = new File(INDEXPATH);
Directory directory = null;
IndexWriter indexWriter = null;
if (file != null) {
FileUtils.deleteDirectory(file);
directory = LuceneUtil.getDirectory(INDEXPATH);
indexWriter = LuceneUtil.getIndexWriter(directory, new SmartChineseAnalyzer());
List<Map<String, Object>> maps = diaryService.listPager(null, null);

String contentText = "";
for (Map diary : maps) {
Document doc = new Document();
doc.add(new StringField("did", String.valueOf(diary.get("did")), Field.Store.YES));
doc.add(new TextField("title", (String) diary.get("title"), Field.Store.YES));
doc.add(new StringField("releaseDate", DateUtil.formatDate((Date) diary.get("releaseDate"), "yyyy-MM-dd"), Field.Store.YES));
contentText = Jsoup.parse((String) diary.get("content")).text();
doc.add(new TextField("content", contentText, Field.Store.YES));
indexWriter.addDocument(doc);
}
}
LuceneUtil.close(indexWriter, directory);
System.out.println("-------------------------结束生成索引-------------------------");
}

/**
* 按关键字索引日记
* @param q
* @return
* @throws Exception
*/
public List<Diary> searchDiary(String q) throws Exception {
Directory directory = LuceneUtil.getDirectory(INDEXPATH);
DirectoryReader reader = LuceneUtil.getDirectoryReader(directory);
IndexSearcher searcher = LuceneUtil.getIndexSearcher(reader);
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
//拿一句话到索引目中的索引文件中的词库进行关键词碰撞
Query query = new QueryParser("title", analyzer).parse(q);
Query query2 = new QueryParser("content", analyzer).parse(q);
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
booleanQuery.add(query, BooleanClause.Occur.SHOULD);
booleanQuery.add(query2, BooleanClause.Occur.SHOULD);

//优先高亮title
Highlighter highlighter = LuceneUtil.getHighlighter(query, "title");
//组合高亮
TopDocs topDocs = searcher.search(booleanQuery.build(), 100);
//处理得分命中的文档
List<Diary> diaryList = new ArrayList<>();
Diary diary = null;
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
Document doc = searcher.doc(scoreDoc.doc);
diary = new Diary();
diary.setDid(Integer.valueOf(doc.get("did")));
diary.setReleaseDateStr(doc.get("releaseDate"));
String title = doc.get("title");
String content = StringEscapeUtils.escapeHtml4(doc.get("content"));
if (title != null) {
TokenStream tokenStream = analyzer.tokenStream("title", new StringReader(title));
String hTitle = highlighter.getBestFragment(tokenStream, title);
if (StringUtils.isBlank(hTitle)) {
diary.setTitle(title);
} else {
diary.setTitle(hTitle);
}
}

if (content != null) {
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(content));
String hContent = highlighter.getBestFragment(tokenStream, content);
if (StringUtils.isBlank(hContent)) {
if (content.length() <= 200) {
diary.setContent(content);
} else {
diary.setContent(content.substring(0, 200));
}
} else {
diary.setContent(hContent);
}
}
diaryList.add(diary);
}
LuceneUtil.close(reader, directory);
return diaryList;
}
}
3、对应的controller层、service实现类代码(因为我有部分逻辑是在service实现类里进行处理的)

controller层:
/**
* 保存或者修改日记
* @param req
* @param diary
* @return
*/
@RequestMapping("/save")
public String save(HttpServletRequest req,Diary diary) {
this.diaryService.save(diary);
req.setAttribute("view", "/diary/edit");
return "redirect:/user/mainTemp";
}

/**
* 删除日记
* @param req
* @param did
* @return
*/
@RequestMapping("/del/{did}")
public String del(HttpServletRequest req,@PathVariable("did")Integer did) {
this.diaryService.del(did);
return "redirect:/user/mainTemp";
}

/**
* 将全部的博客索引文件重新生成
* @return
*/
@ResponseBody
@RequestMapping("/indexDiarys")
public Map indexDiarys(){
Map map = new HashMap();
try {
diaryIndex.indexDiarys();
map.put("success",true);
} catch (Exception e) {
e.printStackTrace();
}
return map;
}

/**
* 根据关键字查询相关博客信息
* @param q
* @return
* @throws Exception
*/
@RequestMapping("/q")
public ModelAndView search(@RequestParam(value="q",required=false) String q, HttpServletRequest request)throws Exception{
PageBean pageBean = new PageBean();
pageBean.setRequest(request);
ModelAndView mav=new ModelAndView("mainTemp");
mav.addObject("view", "/diary/result");

//开始索引日记
List<Diary> diaryList=diaryIndex.searchDiary(q);

pageBean.setTotal(diaryList.size());
int endIndex = Math.min(pageBean.getPage() * pageBean.getRows(), diaryList.size());
//查询出符合条件的所有记录然后进行截取
mav.addObject("diaryList", diaryList.subList(pageBean.getStartIndex(), endIndex));
//上一页、下一页的链接
mav.addObject("q", q);
mav.addObject("resultTotal", pageBean.getTotal());
mav.addObject("pageCode", PageUtil.createPageCode(pageBean));
return mav;
}
service实现类:
@Override
public int save(Diary diary) {
try {
if (diary.getDid() == null || diary.getDid() == 0){
int i = this.diaryMapper.add(diary);
diaryIndex.addIndex(diary);
return i;
}
else {
diaryIndex.updateIndex(diary);
return this.diaryMapper.update(diary);
}
}catch (Exception e){
e.printStackTrace();
return 0;
}
}

@Override
public int del(Integer did) {
try {
diaryIndex.deleteIndex(did + "");
} catch (Exception e) {
e.printStackTrace(http://www.my516.com);
}
return this.diaryMapper.del(did);
}

---------------------

转载于:https://www.cnblogs.com/hyhy904/p/11173759.html

Lucene使用案例(包括索引的维护)相关推荐

  1. mysql 索引案例与索引策略

    目录 索引案例学习 支持多种过滤条件 避免多个范围条件 优化排序 分页查询优化 分而治之总是不错的 索引高性能策略 策略总结 独立的列 前缀索引和索引选择性 多列索引 选择合适的索引列顺序 聚簇索引 ...

  2. 基于lucene的案例开发:纵横小说章节列表采集

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44854719 http://www.llwjy.com/blogdetail/d ...

  3. Oracle索引的维护

    原 Oracle 索引的维护https://blog.csdn.net/tianlesoftware/article/details/5680706版权声明: https://blog.csdn.ne ...

  4. mysql 复制表结构(包括索引等)、表内容

    =============================================== 2019/7/16_第1次修改                       ccb_warlock == ...

  5. 基于lucene的案例开发:纵横小说简介页采集

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44851419 http://www.llwjy.com/blogdetail/1 ...

  6. 基于lucene的案例开发:纵横小说数据库操作

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/46785223 http://www.llwjy.com/blogdetail/e ...

  7. Lucene源代码之信息索引

    索引是什么?索引是一种数据存储和组织结构. 逆常人之思维,lucene索引采用倒排文件索引构造索引系统.具体实现原理举例说明: 假设有3篇文章,file1,file2,file3,文件内容如下: fi ...

  8. (三)Lucene——Field域和索引的增删改

          1. Field域 1.1  Field的属性 是否分词(Tokenized) 是:对该field存储的内容进行分词,分词的目的,就是为了索引. 比如:商品名称.商品描述.商品价格 否:不 ...

  9. Lucene.Net 初学笔记 - 索引

    上次随笔写的Lucene.Net 初学笔记 - 介绍,有许多前辈让我知道了Lucene.Net已经不再更新,最后的版本写到2.9.2,不过只更新在svn上.我上次下载是官方正式发布的版本,只有2.0. ...

最新文章

  1. 云主机启动提示Booting from Hard Disk GRUB
  2. redux和react-redux的使用详解
  3. redis(nosql数据库)
  4. 学习笔记Hive(二)—— Hive安装配置
  5. c# uri.host_C#| Uri.IsHexEncoding()方法与示例
  6. ElasticSearch聚合查询
  7. 数据3分钟丨GitHub开放全世界最大安全咨询数据库;DataBench-T正式开源;甲骨文283亿美元收购Cerner...
  8. STM32工作笔记0019---新建工程模板-基于固件库-M3
  9. Forefront TMG 2010 篇(二)--安装
  10. 巧技拾遗 | JavaScript 中 Array.every 和 Array.map 的巧妙结合
  11. sql server动态分页
  12. ftp服务器多用文件夹权限,自己动手搭建隔离用户的FTP服务器之权限分配(二)...
  13. java俄罗斯方块代码_[转载]java编写的一个俄罗斯方块(源代码)
  14. rootkit后门检测工具rkhunter
  15. [Inception V1]赫布学习理论(Hebbian theory)
  16. springboot读取xml配置文件
  17. 多少层楼听不见街边噪音_街边刮板
  18. C#把月日年帶有 AM、PM的时间格式转换为正常时间格式
  19. 现代计算机发展经历的阶段,计算机的发展经历了那几个阶段
  20. 基于Pygame中Pygame模块的大战外星人

热门文章

  1. php版本最低要求:5.4_Zabbix 5.0.0beta1版本初体验
  2. 猴子选大王c语言课程设计,【C/C++】猴子选大王
  3. springmvc rest风格化案例
  4. 京东数科上市首轮问询「答卷」:与蚂蚁集团有本质区别、信用风险损失有限
  5. vs2012打包和部署程序成可安装安装包文件(InstallShield
  6. python textwrap_python2.7.3编译python模块学习- textwrap 文本包装和填充
  7. HashMap的7种遍历方式
  8. Builder 模式
  9. TensorFlow学习笔记(六)Variable变量
  10. 无法连接 服务器/虚拟机中的数据库,报错Access denied for user ‘root‘@‘192.168.1.101‘