Lucene相关介绍(二)

在这篇博文中呢,我们会给出大家一个创建索引的实例和搜索的实例,结合例子给大家讲解建索引和搜索的核心过程!

 

我们先给出一个Lucene建立索引的例子:

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;

public class  Index{

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		// 保存索引文件的地方
		String indexDir = "C:\\Users\\ZEQ\\Desktop\\ZZUluceneTest1\\index";
		// 将要搜索TXT文件的地方
		String dateDir = "C:\\Users\\ZEQ\\Desktop\\ZZUluceneTest1\\data";
		IndexWriter indexWriter = null;
		// 创建Directory对象 ,FSDirectory代表待索引的文件存在磁盘上
		Directory dir = new SimpleFSDirectory(new File(indexDir));
		// 创建IndexWriter对象,第一个参数是Directory,第二个是分词器,第三个表示是否是创建,如果为false为在此基础上面修改,第四表示表示分词的最大值,比如说new
		// MaxFieldLength(2),就表示两个字一分,一般用IndexWriter.MaxFieldLength.LIMITED
		indexWriter = new IndexWriter(dir, new StandardAnalyzer(
				Version.LUCENE_30), true, IndexWriter.MaxFieldLength.UNLIMITED);
		
		
		File[] files = new File(dateDir).listFiles();
		for (int i = 0; i < files.length; i++) {
			Document doc = new Document();
			// 创建Field对象,并放入doc对象中
			
			doc.add(new Field("id", i+"", Field.Store.YES,
					Field.Index.NOT_ANALYZED));
			doc.add(new Field("contents", new FileReader(files[i])));
			
			doc.add(new Field("path", files[i].getAbsolutePath(), Field.Store.YES,
					Field.Index.ANALYZED));
			doc.add(new Field("indexDate", DateTools.dateToString(new Date(),
					DateTools.Resolution.DAY), Field.Store.YES,
					Field.Index.NOT_ANALYZED));
			// 写入IndexWriter
			indexWriter.addDocument(doc);
		}
		// 查看IndexWriter里面有多少个索引
		System.out.println("总共------》" + indexWriter.numDocs());
		
		indexWriter.close();

	}

}


以上是给txt文档建立索引的一个例子,我们通过这个例子来理解Lucene建立索引的核心过程~

 

在这里呢有必要说一下,Lucene各个版本不一样,有较大的差异~~~在这里能我们用的是Lucene3.0版本

 

我们通过上面的例子可以看出,执行索引的类关键有以下几个:

1,IndexWriter

2,Directory

3,Analyzer

3,Document

4,Field

我们来看一下,建立索引的过程:

 

 

 

下面我们将分别对各个类进行详细介绍。

 

IndexWriter

           IndexWriter(写索引)是索引过程的核心组件。这个类负责创建新索引和打开已有索引,以及向索引中添加,删除和更新被索引的信息。可以把IndexWriter看作这样一个对象:他为你提供针对索引文件的写入操作,但不能用于读取或搜索索引。IndexWriter需要开辟一定的空间来存储索引,该功能可由Directory完成。

 

Directory

          Directory类描述了索引存放的位置。他是一个抽象类,他的子类负责具体指定索引的存储路径。在以上的例子中,我们使用FSDirectory.open方法获取真实文件的文件系统的存储路径,然后将它们依次传递给IndexWriter类构造方法。

Lucene中包含大量的有趣的Directory实现,具体的请参考了类文档说明,IndexWriter不能直接索引文本,需要先由Analyzer将文本分成独立的单才行!

 

Analyzer

       文本文件再被索引之前,需要先被Analyzer(分析器)进行处理。Analyzer是由IndexWriter的构造方法来制定的,他负责从被索引文本文件中提取语汇单元,并提出剩下的无用信息。如果被索引被容不是纯文本,那就需要将其转换为文本文档。Tika可以从常用的媒体格式文件中提取文本内容。Analyzer是一个抽象类,而Lucene提供了几个类来实现它,比如:StandardAnalyzer,SimpleAnalyzer等,除此之外呢,还可以用第三方的分析器IKAnalyzer使用,IKAnalyzer提供了强大的中文分析词,相关介绍将会在以后博文中进行详细介绍。这些类有的用于跳过停用词(stop words)(指一些常用的且不能帮助区分文档的词,如:an ,a,the ,in, on等等)用的用于把语汇单元转换成小写形式,以使搜索过程中忽略大小写区别;除此之外还有一些其他的类。Analyzer是Lucene中很重要的一项,它的功能不仅仅是过滤输入这一项。选择什么样的Analyzer是很关键的一步,当然可以使用第三方的IKAnalyzer。想写的Analyzer介绍,请查看网上相关的文档。

 

Document

        Document(文档)对象代表一些域(Field)的集合。你可以将Document对象理解为虚拟文档-----比如:web页面,E-mail信息,或者文本文件--------然后,你可以从中取回大量数据,文档的域代表文档或者和文档相关的元数据。文档的数据(比如数据库记录,word文档,书中的某一章)对于Lucene来说是无关紧要的。Lucene只处理从二进制文档中提取的以Field实例形式出现的文本。上述例子中的的元数据(path,contents)都作为文档的不同域单独存储并索引。Document对象的结构比较简单,为一个包含多个Field对象的容器,Field是指包含能被索引的文本内容。

 

Field

     索引中的每个文档都包含一个或多个不同命名的域,这些域包含在Field类中。每个域都有一个域名和域值,以及一组选项来精确控制Lucen,索引操作各个域值。文档可以拥有不止一个同名的域。在这种情况下,域的值就按照索引操作顺序添加进去。在搜索时,所有域的文本就好像连接在一起,作为一个文本域来处理。

     在使用Lucene进行索引操作时,上述几个类是最常用的,为了实现最基本的搜索功能,你需要熟悉同样小而且简单的Lucene搜索类。

 

 

    好了,到此为止,我们已经了解了Lucene创建索引的一些核心类。接下来,我们同样会给出一个Lucene搜索的例子,来为大家讲解Lucene搜索的核心类。

 

 

 
import java.io.File;
import java.util.Date;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
/**
 * @author ht
 * 查询
 *
 */
public class Seacher {
	private static String INDEX_DIR = "C:\\Users\\ZEQ\\Desktop\\ZZUluceneTest1\\index";//索引所在的路径
	private static String KEYWORD = " ";//关键词
	private static int TOP_NUM = 10;//显示前10条结果
	
	public static void main(String[] args) throws Exception {
		File indexDir = new File(INDEX_DIR);
	    if (!indexDir.exists() || !indexDir.isDirectory()) {
	    	throw new Exception(indexDir +" 该目录不存在~~");
	    }
	    search(indexDir, KEYWORD);//调用search方法进行查询
	}
	/**查询
	 * @param indexDir
	 * @param q
	 * @throws Exception
	 */
	public static void search(File indexDir, String q) throws Exception {
	    IndexSearcher is = new  IndexSearcher(FSDirectory.open(indexDir),true);//read-only
	    String field = "contents";
	    
	    QueryParser parser = new QueryParser(Version.LUCENE_30, field, new StandardAnalyzer(Version.LUCENE_30));//有变化的地方
	    Query query = parser.parse(q);
	
	    TopScoreDocCollector collector = TopScoreDocCollector.create(TOP_NUM , false);//有变化的地方
	    
	    long start = new Date().getTime();// start time
	    
	    is.search(query, collector);
	    ScoreDoc[] hits = collector.topDocs().scoreDocs;
	
	    
	    for (int i = 0; i < hits.length; i++) {
	    	Document doc = is.doc(hits[i].doc);//new method is.doc()
	    	System.out.println("路径:"+doc.get("path")+"---------------------"+doc.getField("path")+"\n创建时间:"+doc.get("indexDate"));
	    	
		}
	    long end = new Date().getTime();//end time
	
	    System.out.println("\n找到" + collector.getTotalHits() +
	    	      "个结果,总共花费时间 : " + (end - start)+"毫秒"
	    	      );
	  }
}


 

 

通过上述搜索索引的例子可以看出,很简单,涉及到的核心类如下:

1,IndexSearcher

2,QueryParser

3,Query

4,TopDocs

      

 IndexSearcher

           IndexSearcher类用于搜索由IndexWriter创建的索引:这几个类公开了几个搜索方法,它是连接索引的中心环节。可以将IndexSearcher类看作一个以只读方式打开索引的类。他需要利用Directory实例来掌控前期创建的索引,然后才能提供大量的搜索方法,其中一些方法在他的抽象父类Query中实现,最简单的搜索方法是将当个Query对象和int topN 计数作为该方法的参数,并返回TopDocs对象。用法如下:

以上代码是一种搜索的方式,以下也是一种:

Directory dir=FSDirectory.open("c:/index");//打开索引目录

IndexSearcher searcher=new IndexSearcher(dir);//创建查找索引对象

Query query=new TermQuery(new Term("contents","lucene"));//在contents域中查找lucene关键字

TopDocs  hits=searcher.searcher(query,10);//取出前10条记录

for(ScoreDoc scoreDoc:hits.scoreDocs){
Document doc=searcher.doc(scoredoc.doc);
System.out.Println(doc.get("contents"));//获取包含关键字lucene的contents域的值
}




 


 

Query

    Lucene包含很多具体的Query子类,到目前为止,Lucene的基本的Query子类 :TermQuery类。还有其他的类:BooleanQuery,PhraseQuery ,PrefixQuuery,PhrasePrefixQuery,TermRangeQuery,NumericRangeQuery,FilteredQuery和SpanQuery。Query是他们的所有共同的父类,

 

TopDocs

 

     TopDocs类是一个简单的指针容器,指针一般指向前N个排名的搜索结果,搜索结果即匹配查询条件的文档。TopDocs会记录前N个结果中每个结果的int docID(可以用来恢复文档)和浮点型分数。

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值