一、添加支持的jar包
pom.xml
<!-- 添加lucene支持 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>5.3.1</version>
</dependency>
二、代码编写
package cn.sp.lucene;
import java.io.StringReader;
import java.nio.file.Paths;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang.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.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
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.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import cn.sp.entity.Blog;
import cn.sp.util.DateUtil;
import cn.sp.util.StringUtil;
/**
* 博客Lucene索引类
* @author 2YSP
*
*/
public class BlogIndex2 {
private Directory dir;
/**
* 获取indexWriter实例
* @return
* @throws Exception
*/
public IndexWriter getWriter() throws Exception{
//词典保存目录
dir = FSDirectory.open(Paths.get("D:\\lucene"));
//分词器
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
IndexWriter indexWriter = new IndexWriter(dir, config);
return indexWriter;
}
/**
* 添加博客索引
* @param blog
* @throws Exception
*/
public void addIndex(Blog blog) throws Exception{
//获取writer对象
IndexWriter writer = getWriter();
//文档对象
Document doc = new Document();
//参数1.相当于key 2.值 3.是否保存
//主键
doc.add(new StringField("id", String.valueOf(blog.getId()), Store.YES));
//博客标题
doc.add(new TextField("title", blog.getTitle(), Store.YES));//保存索引
//博客内容,不包含html标签的纯文本
doc.add(new TextField("content", blog.getContentNoTag(), Store.YES));
//发布日期
doc.add(new StringField("releaseDate", blog.getReleaseDateStr(), Store.YES));
//添加
writer.addDocument(doc);
//关闭资源
writer.close();
}
/**
* 删除索引
* @param id
*/
public void delIndex(String id)throws Exception{
//获取writer对象
IndexWriter writer = getWriter();
//删除
writer.deleteDocuments(new Term("id",id));
//强制删除
writer.forceMergeDeletes();
//事物提交
writer.commit();
//关闭资源
writer.close();
}
/**
* 修改索引 和添加很类似
* @param blog
*/
public void updateIndex(Blog blog)throws Exception{
//获取writer对象
IndexWriter writer = 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 StringField("releaseDate", DateUtil.formatDate(new Date(), "yyyy-MM-dd"), Field.Store.YES));//发布日期
doc.add(new TextField("content", blog.getContentNoTag(), Field.Store.YES));
//修改,根据id更新
writer.updateDocument(new Term("id", String.valueOf(blog.getId())), doc);
//关闭资源
writer.close();
}
/**
* 查询博客
* @param keyWord
* @return
* @throws Exception
*/
public List<Blog> searchBlog(String keyWord) throws Exception{
dir = FSDirectory.open(Paths.get("D:\\lucene"));
//获取indexReader
IndexReader reader = DirectoryReader.open(dir);
//搜索对象
IndexSearcher searcher = new IndexSearcher(reader);
//多个条件
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
//查询解析器
QueryParser parser = new QueryParser("title",analyzer);
//解析后获得查询对象
Query query = parser.parse(keyWord);
QueryParser parser2 = new QueryParser("content",analyzer);
Query query2 = parser2.parse(keyWord);
//封装
booleanQuery.add(query, Occur.SHOULD);//应该发生,非必须条件
booleanQuery.add(query2, Occur.SHOULD);
//只查询前100条
TopDocs hits = searcher.search(booleanQuery.build(), 100);
//以标题为计分器
QueryScorer queryScorer = new QueryScorer(query);
Fragmenter fragmenter = new SimpleSpanFragmenter(queryScorer);
//字体加红加粗
SimpleHTMLFormatter htmlFormatter = new SimpleHTMLFormatter("<b><font color='red'>", "</font></b>");
Highlighter lighter = new Highlighter(htmlFormatter, queryScorer);
lighter.setTextFragmenter(fragmenter);
List<Blog> blogList = new LinkedList<Blog>();
for(ScoreDoc scoreDoc: hits.scoreDocs){
Document doc = searcher.doc(scoreDoc.doc);
//封装blog对象
Blog blog = new Blog();
blog.setId(Integer.parseInt(doc.get("id")));
blog.setReleaseDateStr(doc.get("releaseDate"));
String title = doc.get("title");
String content = StringEscapeUtils.escapeHtml(doc.get("content"));//去html
if(title != null){
TokenStream tokenStream = analyzer.tokenStream("title", new StringReader(title));
String hTitle = lighter.getBestFragment(tokenStream, title);
if(StringUtil.isEmpty(hTitle)){//没有高亮的
blog.setTitle(title);//不含关键字的
}else{
blog.setTitle(hTitle);//高亮的
}
}
if(content != null){
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(content));
String hContent = lighter.getBestFragment(tokenStream, content);
if(StringUtil.isEmpty(hContent)){
if(content.length() > 200){
//内容限制200
blog.setContent(content.substring(0,200));
}else{
blog.setContent(content);
}
}else{
blog.setContent(hContent);
}
}
//添加到集合
blogList.add(blog);
}
return blogList;
}
}