您的位置:首页 > 其它

使用Lucene建立索引

2012-06-19 17:02 435 查看
最近在看Lucene in Action这本书的原著,第一步就是建立要建立文件索引,当然文件必须为统一的格式,Lucene不支持异构文件。

我练习了书中的listing 1.1:Indexer,由于我使用的是Lucene3.5版本,而书中使用的3.0,3.5和3.0是有一些差异的!

package org.apache.lucene.indexer;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public class Indexer {

	private IndexWriter writer = null;
	
	/**
	 * 完成索引建立
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		if(args.length != 2)
		{
			throw new Exception("Usage: java"+Indexer.class.getName()
					+"<index dir> <data dir>");
		}
		//存放索引的目录
		String indexDir = args[0];
		//需要被索引的文件存放的目录
		String dataDir = args[1];
		//用来测试Lucene建立索引所耗时间
		long start = System.currentTimeMillis();
		Indexer indexer = new Indexer(indexDir);
		int numIndexed = indexer.index(dataDir);
		indexer.close();
		long end = System.currentTimeMillis();
		System.out.println("Indexing "+numIndexed+" use "+(start-end)+"milliseconds");
	}

	/**
	 * 构造函数
	 * @param indexDir
	 * @throws IOException 
	 */
	public Indexer(String indexDir) throws IOException {
		//  Creates an FSDirectory instance, trying to pick the best implementation given the current environment.
		Directory dir = FSDirectory.open(new File(indexDir));
		//3.5版本之后使用这种方式来建立writer,参数:版本号,标准分词器
		IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
		writer = new IndexWriter(dir, iwc);
	}
	
	/**
	 * 把存放的文件建立为索引
	 * @param dataDir
	 * @return writer.numDocs
	 * @throws IOException 
	 */
	private int index(String dataDir) throws IOException {
		//得到所有文件,listFiles为遍历文件
		File[] files = new File(dataDir).listFiles();
		for(int i=0; i<files.length; i++)
		{
			File f = files[i];
			if(!f.isDirectory() && !f.isHidden()
				&& f.canRead() && acceptFile(f))
			{
				indexFile(f);
			}
		}
		return writer.numDocs();
	}

	/**
	 * 把文档加入Lucene的索引中
	 * @param f
	 * @throws IOException 
	 */
	private void indexFile(File f) throws IOException {
		//getCanonicalPath,更加通用,可以包含特殊字符,跨平台
		//Returns the canonical pathname string of this abstract pathname.
		System.out.println("Indexing"+f.getCanonicalPath());
		Document doc = getDocument(f);
		if(doc != null)
		{
			writer.addDocument(doc);
		}
	}

	/**
	 * 对文档进行索引,此处只对文档的内容和名称域进行索引
	 * @param f
	 * @return doc
	 * @throws IOException 
	 */
	private Document getDocument(File f) throws IOException {
		Document doc = new Document();
		//内容可以不做存储
		doc.add(new Field("contents", new FileReader(f)));
		//文件名存储,建立索引,但是依据情况没有必要对其进行分词
		doc.add(new Field("filename", f.getCanonicalPath(),Field.Store.YES,Field.Index.NOT_ANALYZED));
		return doc;
	}

	/**
	 * 只允许对.txt文件作出处理,把它进行索引
	 * @param f
	 * @return 
	 */
	private boolean acceptFile(File f) {
		return f.getName().endsWith(".txt");
	}

	/**
	 * 当索引建立成功时,要记得关闭writer
	 * @throws IOException 
	 * @throws CorruptIndexException 
	 */
	private void close() throws CorruptIndexException, IOException {
		writer.close();
	}
}


在输入参数(D:\abc\lucene\index03 D:\abc\lucene)之后,运行结果为:

IndexingD:\abc\lucene\abc.txt
IndexingD:\abc\lucene\car.txt
IndexingD:\abc\lucene\hello.txt
Indexing 3 use -1156milliseconds

以上程序中用到的类简要介绍:

IndexWriter

这个类可以建立一个新的索引或者打开一个已经存在的索引,

可以对索引进行增删改,但是不可以搜索和读取

Directory是IndexWriter存放索引的地方

FSDirectory在文件系统中存,RAMDirectory存在内存中(这样会更小、更快捷、应用关闭的时候就会销毁

但是缺点是不能持久化)这种方法适合于需要快速访问索引的时候,包括建立索引和搜索索引。

Analyer

IndexWriter不能索引文件除非它被分割成单个的词。

首先把文件的内容转变为有格式的形式。

它是一个抽象类,Lucene提供了一些实现方法。

分词器通过处理停词(不能作为区分文档的词,如a,the等)

把字符转为小写以便搜索的时候不区分大小写

一个合适的分词器能够对搜索的准确性提供很大帮助

Document

分词器需要一个包含独立字段的文档来索引

文档中有很多字段,这些字段都可以存放到索引中

Lucene只处理text格式的文档,

Feild

每个字段有若干个名称和其对应的值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: