lucene使用教程3 --常用类的对象

你需要以下类来执行这个简单的索引与搜索的过程:

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());
			}
		}

	}






你可能感兴趣的:(lucene使用教程3 --常用类的对象)