博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
全文检索Lucene (2)
阅读量:6271 次
发布时间:2019-06-22

本文共 9448 字,大约阅读时间需要 31 分钟。

接着 。 下面我们来深入的研究一下,如何使用Lucene!

从中我们可以看出,Lucene就好比一个双向的工作流,一方面是对索引库的维护,另一方面是对查询过程的支持。同时,这也是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); } } /** * 更新索引
* 更新操作代价很高,一般采取先删除对应的索引,然后在创建这个索引的方式 * * @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
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
articles = new ArrayList
(); 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版本有困难的小伙伴能从中收获到自己需要的内容。

你可能感兴趣的文章
【转】如何实现一个配置中心
查看>>
Docker —— 用于统一开发和部署的轻量级 Linux 容器【转】
查看>>
Threejs 官网 - Three.js 的图形用户界面工具(GUI Tools with Three.js)
查看>>
Atitit.Java exe bat 作为windows系统服务程序运行
查看>>
session的生命周期
查看>>
数据库的本质、概念及其应用实践(二)
查看>>
iOS开发多线程--(NSOperation/Queue)
查看>>
php的ajax简单实例
查看>>
maven常用构建命令
查看>>
C#:关联程序和文件
查看>>
推荐科研软件
查看>>
gradle
查看>>
如何取消未知类型文件默认用记事本打开
查看>>
[Javascript] Immute Object
查看>>
Java 关于finally、static
查看>>
Posix mq和SystemV mq区别
查看>>
P6 EPPM Manual Installation Guide (Oracle Database)
查看>>
XMPP协议、IM、客户端互联详解
查看>>
PHP写文件函数
查看>>
mysql的sql_mode合理设置
查看>>