全文检索Lucene (2)
接着全文检索Lucene (1) 。 下面我们来深入的研究一下,如何使用Lucene!
从全文检索Lucene (1)中我们可以看出,Lucene就好比一个双向的工作流,一方面是对索引库的维护,另一方面是对查询过程的支持。同时,这也是Lucene的优雅所在。
Lucene索引库构建分析
Lucene查询过程分析
范例分析
下面我会写一个小的demo,大致的功能就是CRUD
。类比JDBC
,我们不可避免的要写一些工具类来优化我们的代码,减少重复代码。
Article.java
/**
* @Date 2016年8月1日
*
* @author Administrator
*/
package domain;
/**
* @author 郭瑞彪
*
*/
public class Article {
private Integer id;
private String title;
private String content;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
@Override
public String toString() {
return "Article [id=" + id + ", title=" + title + ", content=" + content + "]";
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
LuceneUtils.java
/**
* @Date 2016年8月1日
*
* @author Administrator
*/
package util;
import java.io.IOException;
import java.nio.file.Paths;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
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.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
/**
* @author 郭瑞彪
*
*/
public class LuceneUtils {
private static Directory dir;
public static Directory getDir() {
return dir;
}
public static Analyzer getAnalyzer() {
return analyzer;
}
private static Analyzer analyzer;
/**
* 获得一个用于操作索引库的IndexWriter对象
*
* @return
*/
public static IndexWriter getIndexWriter() {
try {
Directory dir = FSDirectory.open(Paths.get("./indexDir/"));
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(new StandardAnalyzer());
IndexWriter indexWriter = new IndexWriter(dir, indexWriterConfig);
return indexWriter != null ? indexWriter : null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 获得一个索引库查询对象
*
* @return
*/
public static IndexSearcher getIndexSearcher() {
try {
DirectoryReader directoryReader = DirectoryReader.open(FSDirectory.open(Paths.get("./indexDir/")));
IndexReader indexReader = directoryReader;
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
return indexSearcher != null ? indexSearcher : null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 释放IndexWriter资源
*
* @param indexWriter
*/
public static void closeIndexWriter(IndexWriter indexWriter) {
try {
if (indexWriter != null) {
indexWriter.close();
indexWriter = null;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 释放IndexSearcher资源
*
* @param indexSearcher
*/
public static void closeIndexSearcher(IndexSearcher indexSearcher) {
try {
if (indexSearcher != null) {
indexSearcher = null;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ArticleDocument.java
/**
* @Date 2016年8月1日
*
* @author Administrator
*/
package util;
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 domain.Article;
/**
* @author 郭瑞彪
*
*/
public class ArticleDocumentUtils {
/**
* Article转换成Licene的Document
*
* @param article
* @return
*/
public static Document article2Document(Article article) {
Document doc = new Document();
doc.add(new StringField("id", article.getId().toString(), Store.YES));
doc.add(new TextField("title", article.getTitle(), Store.YES));
doc.add(new TextField("content", article.getContent(), Store.YES));
return doc != null ? doc : null;
}
/**
* 将Document转换回Article
*
* @param document
* @return
*/
public static Article document2Article(Document document) {
Article a = new Article();
a.setId(Integer.parseInt(document.get("id")));
a.setTitle(document.get("title"));
a.setContent(document.get("content"));
return a != null ? a : null;
}
}
ArticleIndexDao.java
/**
* @Date 2016年8月1日
*
* @author Administrator
*/
package dao;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
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.util.Version;
import domain.Article;
import domain.Page;
import util.ArticleDocumentUtils;
import util.LuceneUtils;
/**
* @author 郭瑞彪
*
*/
public class ArticleIndexDao {
/**
* 将新的数据保存到索引库
*
* @param article
*/
public void save(Article article) {
IndexWriter indexWriter = null;
try {
// 1. article --> document
Document doc = ArticleDocumentUtils.article2Document(article);
// 2. indexWriter.addDocument(document)
indexWriter = LuceneUtils.getIndexWriter();
indexWriter.addDocument(doc);
// 临时代码
indexWriter.close();
} catch (IOException e) {
throw new RuntimeException("ArticleIndexDao--save方法出错!\n" + e);
} finally {
LuceneUtils.closeIndexWriter(indexWriter);
}
}
/**
* 删除索引
*
* @param id
*/
public void delete(Integer id) {
IndexWriter indexWriter = null;
try {
indexWriter = LuceneUtils.getIndexWriter();
indexWriter.deleteDocuments(new Term("id", id.toString()));
} catch (IOException e) {
throw new RuntimeException("ArticleIndexDao--save方法出错!\n" + e);
} finally {
LuceneUtils.closeIndexWriter(indexWriter);
}
}
/**
* 更新索引 <br>
* 更新操作代价很高,一般采取先删除对应的索引,然后在创建这个索引的方式
*
* @param article
*/
public void update(Article article) {
IndexWriter indexWriter = null;
try {
Term term = new Term("id", article.getId().toString());
indexWriter = LuceneUtils.getIndexWriter();
// Document doc = new Document();
// doc.add(new TextField("title", article.getTitle(), Store.YES));
// doc.add(new TextField("content", article.getContent(),
// Store.YES));
// indexWriter.updateDocument(new Term("title", "content"), doc);
// 优化版本的实现就是:先删除愿索引,然后再创建该索引
indexWriter.deleteDocuments(term);
Document doc = ArticleDocumentUtils.article2Document(article);
indexWriter.addDocument(doc);
} catch (IOException e) {
throw new RuntimeException("ArticleIndexDao--save方法出错!\n" + e);
} finally {
LuceneUtils.closeIndexWriter(indexWriter);
}
}
/**
* 从索引库中查询
*
* @param queryString
* 查询字符串
* @return
*/
public List<Article> search(String queryString) {
try {
// 1.queryString -->>Query
String[] queryFields = new String[] { "title", "content" };
Analyzer analyzer = new StandardAnalyzer();
analyzer.setVersion(Version.LUCENE_6_0_0.LUCENE_6_1_0);
QueryParser queryParser = new MultiFieldQueryParser(queryFields, analyzer);
Query query = queryParser.parse(queryString);
// 2. 查询,得到topDocs
IndexSearcher indexSearcher = LuceneUtils.getIndexSearcher();
TopDocs topDocs = indexSearcher.search(query, 100);
// 3.处理结果并返回
int totalHits = topDocs.totalHits;
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
List<Article> articles = new ArrayList<Article>();
for (int i = 0; i < scoreDocs.length; i++) {
ScoreDoc scoreDoc = scoreDocs[i];
Document doc = indexSearcher.doc(scoreDoc.doc);
Article a = ArticleDocumentUtils.document2Article(doc);
articles.add(a);
}
LuceneUtils.closeIndexSearcher(indexSearcher);
return articles.size() > 0 ? articles : null;
} catch (Exception e) {
throw new RuntimeException("ArticleIndexDao-->> search方法出错!\n" + e);
}
}
}
核心操作
关键点:我们在update索引库的时候会花费很大的代价。官网上也建议“先删掉相关索引项,然后在新建这个索引项”。注意Term的使用格式即可。
总结
经JUnit测试,代码可以正常的通过。
当然,代码中可以进行优化的地方还有很多,但是作为演示来说还是差强人意的吧。
希望对于Lucene6.1.0
版本有困难的小伙伴能从中收获到自己需要的内容。
全文检索Lucene (2)的更多相关文章
- 全文检索 Lucene(4)
经过了前面几篇文章的学习,我们基本上可以适用Lucene来开发我们的站内搜索应用了.但是观察一下目前的主流的搜索引擎,我们会发现查询结果会有高亮的显示效果.所以,今天我们就来学习一下,给Lucene添 ...
- 全文检索 Lucene(3)
看完前两篇博客之后,想必大家对于Lucene的使用都有了一个比较清晰的认识了.如果对Lucene的知识点还是有点模糊的话,个人建议还是先看看这两篇文章. 全文检索 Lucene(1) 全文检索 Luc ...
- Lucene 全文检索 Lucene的使用
Lucene 全文检索 Lucene的使用 一.简介: 参考百度百科: http://baike.baidu.com/link?url=eBcEVuUL3TbUivRvtgRnMr1s44nTE7 ...
- 全文检索--Lucene & ElasticSearch
全文检索--Lucene 2.1 全文检索和以前高级查询的比较 1.高级查询 缺点:1.like让数据库索引失效 2.每次查询都是查询数据库 ,如果访问的人比较多,压力也是比较大 2.全文检索框架:A ...
- [全文检索]Lucene基础入门.
本打算直接来学习Solr, 现在先把Lucene的只是捋一遍. 本文内容: 1. 搜索引擎的发展史 2. Lucene入门 3. Lucene的API详解 4. 索引调优 5. Lucene搜索结果排 ...
- 全文检索Lucene (1)
Lucene是apache开源的一个全文检索框架,很是出名.今天先来分享一个类似于HelloWorld级别的使用. 工作流程 依赖 我们要想使用Lucene,那就得先引用人家的jar包了.下面列举一下 ...
- 全文检索-Lucene.net
Lucene.net是Lucene的.net移植版本,在较早之前是比较受欢迎的一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎. ...
- 全文检索Lucene框架---查询索引
一. Lucene索引库查询 对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样Lucene也有自己的查询语法,比如:“name ...
- ]NET Core Lucene.net和PanGu分词实现全文检索
Lucene.net和PanGu分词实现全文检索 Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考 前言:目前自己在做使用Lucene. ...
随机推荐
- Mysql之基本操作与数据类型
进入mysql: mysql -hlocalhost -uroot -p; mysql -uroot -p密码; 查看帮助文档: help 查看名 database(s); 创建数据库: create ...
- python3+dlib人脸识别及情绪分析
一.介绍 我想做的是基于人脸识别的表情(情绪)分析.看到网上也是有很多的开源库提供使用,为开发提供了很大的方便.我选择目前用的比较多的dlib库进行人脸识别与特征标定.使用python也缩短了开发周期 ...
- ABP领域层知识回顾之---实体
标题:重温ABP领域层 1. 前言 最近一段时间一直在看<ABP的开发指南>(基于DDD的经典分层架构思想).因为之前一段时间刚看完<领域驱动设计:软件核心复杂性应对之道>, ...
- [HAOI2007]分割矩阵
题目描述 将一个a*b的数字矩阵进行如下分割:将原矩阵沿某一条直线分割成两个矩阵,再将生成的两个矩阵继续如此分割(当然也可以只分割其中的一个),这样分割了(n-1)次后,原矩阵被分割成了n个矩阵.(每 ...
- Hdu 5595 GTW likes math
题意: 问题描述 某一天,GTW听了数学特级教师金龙鱼的课之后,开始做数学<从自主招生到竞赛>.然而书里的题目太多了,GTW还有很多事情要忙(比如把妹),于是他把那些题目交给了你.每一道题 ...
- JS 实现点击页面任意位置隐藏div、span
通过调用下面的 showhidden(“标签ID”) 显示div/span/…等标签内容,可以实现点击页面任意地方再次隐藏该标签内容,而showhidden(“标签ID”,”nohidden”)可保存 ...
- mybatis添加记录时返回主键id
参考:mybatis添加记录时返回主键id 场景 有些时候我们在添加记录成功后希望能直接获取到该记录的主键id值,而不需要再执行一次查询操作.在使用mybatis作为ORM组件时,可以很方便地达到这个 ...
- java实现微信支付之扫码支付
本文直接从代码调用微信扫码支付讲起.账号配置,参数生成等请参考官方文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1 微信 ...
- Linux的发行版,不同发行版之间的联系和区别
Linux 主要作为Linux发行版(通常被称为"distro")的一部分而使用.这些发行版由个人,松散组织的团队,以及商业机构和志愿者组织编写.它们通常包括了其他的系统软件和应用 ...
- 《Python黑帽子》_1设置Python环境安装wingIDE
1首先你得有个Kali 检测python版本 安装pip 2安装wingIDE 网站 http://www.wingware.com 获取WingIDE 3解压wingide并且解决依赖关系 下载后在 ...