你需要以下类来执行这个简单的索引与搜索的过程:
1、IndexWriter
2、IndexSearcher
3、IndexReader
4、Directory
5、Analyzer
6、Document
7、Field
8、Term
9、Query
10、TermQuery
11、Hits
接下来是对这些类的一个简短的浏览,针对它们在Lucene的角色,给出你粗略的概念。接下来我们开始介绍这些类。
IndexWriter类
IndexWriter是在索引过程中的中心组件。这个类创建一个新的索引并且添加文档到一个已有的索引中。你可以把IndexWriter想象成让你可以对索引进行写操作的对象,但是不能让你读取或搜索。此处使用线程同步的方式确保对象的使用高效、安全和减少内存的压力。
以下代码是从网络上粘贴过来的,代码可能会有错误,但是原理都是一样的,明白原理,什么都简单
MyIndexWriter中对IndexWriter的创建和回收:
public class MyIndexWriter {
private static Analyzer analyzer = new PaodingAnalyzer();
private static IndexWriter indexWriter;
private static ArrayList<Thread> threadList = new ArrayList<Thread>();
private static Directory dir = null;
private MyIndexWriter() {
}
/**
*
* @function 创建indexWriter对象
* @param indexFilePath 创建索引的路径
* @param create 创建方式
* @return
*/
public static IndexWriter getInstance(String indexFilePath, boolean create) {
synchronized (threadList) {
if (indexWriter == null) {
File indexFile = new File(indexFilePath);
File lockfile = new File(indexFilePath + "/write.lock");
try {
if (!indexFile.exists()) {
indexFile.mkdir();
}
dir = FSDirectory.open(indexFile);
if (IndexWriter.isLocked(dir)) {// 判断目录是否已经锁住
IndexWriter.unlock(dir);
}
if (lockfile.exists()) {
lockfile.delete();
}
if (create) {
indexWriter = new IndexWriter(dir, analyzer, true,
MaxFieldLength.UNLIMITED);
} else {
if (IndexReader.indexExists(dir)) {
indexWriter = new IndexWriter(dir, analyzer, false,
MaxFieldLength.UNLIMITED);
} else {
indexWriter = new IndexWriter(dir, analyzer, true,
MaxFieldLength.UNLIMITED);
}
}
indexWriter.setMergeFactor(1000);
indexWriter.setMaxFieldLength(Integer.MAX_VALUE);
// 控制写入一个新的segment前在内存中保存的最大的document数目
indexWriter.setRAMBufferSizeMB(32);
indexWriter.setMaxMergeDocs(200);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
indexFile=null;
lockfile=null;
}
}
if (!threadList.contains(Thread.currentThread()))
threadList.add(Thread.currentThread());
return indexWriter;
}
}
/**
*
* @function 关闭indexWriter对象
*/
public static void close() {
synchronized (threadList) {
if (threadList.contains(Thread.currentThread()))
threadList.remove(Thread.currentThread());
if (threadList.size() == 0) {
try {
if (indexWriter != null) {
indexWriter.optimize();
indexWriter.commit();
indexWriter.close();
indexWriter = null;
}
if (dir != null) {
dir.close();
}
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
使用IndexWriter添加索引
实现过程:把普通对象转换成IndexWriter需要的Documents文档对象,IndexWriter是addDocument()方法把对象索引到文件。
/**
*
* @function 创建文档索引
* @param list 索引对象集合
*/
private static void createDocIndex(List<SearchBean> list,
String indexFilePath, boolean createMode) {
try {
// System.out.println(indexFilePath);
indexWriter = MyIndexWriter.getInstance(indexFilePath + "/index",
createMode);
// 对所有的实体进行索引创建
for (SearchBean searchBean : list) {
// 建立一个lucene文档
doc = new Document();
// 搜索内容
String id = searchBean.getId();
String title = searchBean.getTitle();
String content = searchBean.getContent();
String url = searchBean.getUrl();
String keyword = searchBean.getKeyword();
String time = searchBean.getTime();
String author = searchBean.getAuthor();
String module = searchBean.getModule();
String type = searchBean.getType();
// 添加主键至文档,不分词,不高亮。
doc.add(new Field("id", id, Field.Store.YES,
Field.Index.NOT_ANALYZED, Field.TermVector.NO));
// 利用htmlparser得到处方html的纯文本
Parser parser = new Parser();
parser.setInputHTML(title);
String titleText = parser.parse(null).elementAt(0)
.toPlainTextString().trim();
// 添加到文档
doc.add(new Field("title", titleText, Field.Store.YES,
Field.Index.ANALYZED,
Field.TermVector.WITH_POSITIONS_OFFSETS));
parser.setInputHTML(content);
String contentText = parser.parse(null).elementAt(0)
.toPlainTextString().trim();
// 添加到文档
doc.add(new Field("content", contentText, Field.Store.YES,
Field.Index.ANALYZED,
Field.TermVector.WITH_POSITIONS_OFFSETS));
doc.add(new Field("url", url, Field.Store.YES,
Field.Index.NOT_ANALYZED, Field.TermVector.NO));
doc.add(new Field("keyword", keyword, Field.Store.YES,
Field.Index.ANALYZED,
Field.TermVector.WITH_POSITIONS_OFFSETS));
doc.add(new Field("time", time, Field.Store.YES,
Field.Index.ANALYZED,
Field.TermVector.WITH_POSITIONS_OFFSETS));
doc.add(new Field("author", author, Field.Store.YES,
Field.Index.NOT_ANALYZED, Field.TermVector.NO));
doc.add(new Field("module", module, Field.Store.YES,
Field.Index.NOT_ANALYZED, Field.TermVector.NO));
doc.add(new Field("type", type, Field.Store.YES,
Field.Index.NOT_ANALYZED, Field.TermVector.NO));
indexWriter.addDocument(doc);
}
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
MyIndexWriter.close();
}
}
使用IndexWriter删除索引
删除文档是需要保证的是数据的唯一性,一般把不分词的域作为判断的依据,如果一个域还不能完全保证数据的唯一性,那就需要多个域的组合判断。
下文教你使用组合域删除唯一对象,这是Lucene教程里面没有涉及到的内容,目前使用正常,如果你在使用过程中遇到问题请查阅BooleanQuery的使用方式。
/**
*
* @function 删除
* @param id
* 资源Id
*/
public static void deleteDocument(Long id, String className) {
DictItemBiz dictItemBiz = (DictItemBiz) ac.getBean("dictItemBiz");
TermQuery idQuery = new TermQuery(new Term("id", id + ""));//删除的第一个域
TermQuery resourceQuery = new TermQuery(new Term("type", dictItemBiz.getItemByDictMarkAndItemVal("search_type", className)
.getItemId()
+ ""));//删除的第二个域
BooleanQuery bQuery = new BooleanQuery();
bQuery.add(idQuery, BooleanClause.Occur.MUST);
bQuery.add(resourceQuery, BooleanClause.Occur.MUST);
// 自己的模块的索引更新
String indexFilePath = FILE_PATH
+ConfigurationManager.getInstance().getPropertiesValue(
"common.properties", className + "IndexFilePath")
+ "/index";
try {
deleteDocument(bQuery, indexFilePath);
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
// 重新合并索引
createModuleIndexAndSpellCheck();
}
}
/**
*
* @function 删除文档
* @param bQuery
* @param indexFilePath
* @throws Exception
*/
private static void deleteDocument(BooleanQuery bQuery, String indexFilePath) {
indexWriter = MyIndexWriter.getInstance(indexFilePath, false);
try {
indexWriter.deleteDocuments(bQuery);
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
MyIndexWriter.close();
}
}
使用IndexWriter更新索引
更新索引是一个删除再添加的过程,掌握添加和删除的技巧后,直接运用于更新即可。
使用IndexWriter更新索引合并多个索引文件
在创建索引的过程中,经常会使用不同的情况创建多个不同的索引文件,搜索的时候有时会搜索整个内容,这就需要使用合并索引的技术,虽然你可以创建索引的时候生成一个包含全部内容的索引文件,但是显然这是不合理的方法,这样会浪费大量的内存,在内容较多的情况下极易内存溢出。使用这种合并多个索引的方式使你的程序更加灵活可控。
合并索引文件的关键方法:addIndexesNoOptimize 但是现在Deprecated.use
addIndexes(Directory...)
instead
/**
*
* @function 合并索引文件
* @param fromFilePaths 需要合并的索引文件路径
* @param toFilePath 合并完成的索引文件路径
*/
private static void mergeIndex(String[] fromFilePaths, String toFilePath) {
IndexWriter indexWriter = null;
File file = null;
FSDirectory fsd = null;
try {
// System.out.println("正在合并索引文件!\t ");
indexWriter = MyIndexWriter.getInstance(toFilePath + "/index",
false);
for (String fromFilePath : fromFilePaths) {
file = new File(fromFilePath + "/index");
if (file.exists()) {
fsd = FSDirectory.open(file);
indexWriter.addIndexesNoOptimize(fsd);
}
}
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
} finally {
try {
MyIndexWriter.close();
if (fsd != null) {
fsd.close();
}
file = null;
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
}
}
}
分享到:
相关推荐
doc.add(new TextField("title", "Lucene教程", Field.Store.YES)); doc.add(new TextField("content", "这是关于Lucene的介绍", Field.Store.YES)); indexWriter.addDocument(doc); // 关闭 writer indexWriter....
在Lucene 4.0中,我们需要创建一个`Directory`对象来存储索引,常用的是`FSDirectory`,它将索引存储在文件系统中。接着,我们使用`IndexWriter`类,设定好分词器(Analyzer)和写入参数,然后逐个读取文档,调用`...
3)document包相对而言比较简单,该包下面有3个类,document相对于关系型数据库的记录对象,Field主要负责字段的管理。 4)org.apache.1ucene.index索引管理,包括索引建立、删除等。索引包是整个系统核心,全文检索...
1. **资料的准确性**:由于网络上的信息繁多且质量参差不齐,使用Lucene时要确保所参考的教程或文档是最新的,因为版本更新可能导致某些方法或功能的改变。例如,旧版本中可能使用的`Hits`类在新版本中已被废弃,应...
Lucene是一个高性能、全文本搜索库,它提供了强大的信息检索功能,而布尔搜索是其中一种常用且灵活的搜索方式,允许用户通过逻辑运算符(如AND、OR、NOT等)来组合多个查询条件,以精确地控制搜索结果。 描述部分...
公用类通常包含了与Lucene交互的常用工具和辅助函数,比如索引创建、读取和更新的类,以及分词器和分析器的实现。配置文件则可能涉及到索引设置、内存管理、性能优化等方面,通过分析这些配置,开发者能更好地调整...
Maven学习全教程 Maven是一个基于项目对象模型(POM)的项目管理和构建自动化工具,由Apache软件基金会开发。Maven提供了一个统一的方式来构建、测试、打包和部署项目,使得项目的管理和维护更加容易。 结构概述 -...
它通过提供类似于 Hibernate 的对象关系映射(ORM)功能,使得开发者能够更加轻松地将 Java 对象映射到 Lucene 索引上。与传统的 Lucene 相比,Compass 提供了更高级别的抽象和更简单的 API,从而降低了开发难度。 ...
3. **查询索引**:使用`Analyzer`和`QueryParser`来解析用户输入的查询,生成对应的`Query`对象。然后,通过`IndexSearcher`来执行查询,找到匹配的文档。 4. **获取结果**:`IndexSearcher`返回的搜索结果是一组`...
DOM文档对象模型手册.chm DTD.chm EasyUI-API+1.3.2.chm Ext2.2API中文版.CHM Ext3.2中文API.CHM FILESLIST111.TXT Hibernate3.2.chm html5参考手册.chm HTML入门与提高.CHM Html标签一览表.chm html语法教程.chm ...
SSH框架是Java EE开发中常用的三大框架集成,包括Struts负责控制层,Spring提供依赖注入和事务管理,Hibernate则是持久层的ORM(对象关系映射)工具。Struts作为MVC(模型-视图-控制器)设计模式的实现,负责请求的...
9. **lucene_3.6.1_API.CHM**:Apache Lucene是一个全文搜索引擎库,此文档详细介绍了Lucene 3.6.1版本的API,包括索引构建、查询解析、搜索等功能。 这些CHM文件提供了丰富的编程和Web开发知识,对于学习和提升...
### 开源企业搜索引擎SOLR的应用教程:详细知识点解析 #### 概述 Apache Solr是基于Lucene的高性能、可扩展的企业级全文搜索引擎。它提供了丰富的功能集,包括高度可配置的索引机制、强大的搜索功能以及分布式搜索...
【标题】:“Cassandra入门项目源代码”是一个针对初学者的教程项目,旨在帮助开发者了解如何在Eclipse环境中使用Spring Data框架与EasyRest风格来操作Cassandra数据库和Lucene搜索引擎。这个项目提供了一整套实践性...
最终,考虑到灵活性和扩展性等因素,本教程推荐使用Apache Solr作为企业级搜索引擎解决方案。 ##### 1.2 Solr的特性 **1.2.1 Solr使用Lucene并且进行了扩展** Solr基于Lucene实现,但增加了许多高级功能,例如...
- 描述: Lucene是Java领域的全文搜索引擎库,本书介绍了如何使用Lucene构建搜索引擎。 - **链接**: http://bbs.topsage.com/dispbbs.asp?boardID=121&ID=173991 9. **Java Extreme Programming Cookbook** - ...
- **1.2.1 Solr使用Lucene并且进行了扩展**:Solr基于Apache Lucene构建,不仅继承了Lucene的强大功能,还提供了更高级别的分布式处理能力、更丰富的API支持等。 - **1.2.2 Schema(模式)**:Solr中的模式文件...
- 《JSP实用教程》 - 《Lucene in Action》 这些资料覆盖了Web开发、XML处理、Java服务器页面技术以及全文检索库Lucene等方面的知识,为项目开发提供了理论基础和技术支持。 #### 二、总体设计 ##### 1. 需求概述...
│ DOM文档对象模型手册.chm │ DTD.chm │ EasyUI-API+1.3.2.chm │ Ext2.2API中文版.CHM │ Ext3.2中文API.CHM │ Hibernate3.2.chm │ Hibernate3.2API.chm │ html5参考手册.chm │ HTML入门与提高.CHM │ Html...