首先lucene 是什么,有什么用呢?
个人理解:lucene就是一个开源的建立索引的开源java包。你可以用来对你想要进行索引的文件进行高效快速的建立索引和索引数据。
先抛开理论的分析,先从一些简单实践例子,来了解lucene的功能。
第一步:当然是在官网下载lucene 最新版本。http://lucene.apache.org/
第二步:本地eclipse 建立新的project , 将 刚才下载的lucene 的 jar 包导入到build path中,主要是lucene-core-3.5.0.jar 和 lucene-test-framework-3.5.0.jar 这两个jar包,同时可以把lib下的关联jar也加入path。
第三部:对需要进行查询的文档建立索引。来看一段建立索引代码。
public void createIndex() { Analyzer analyzer = new IKAnalyzer(); IndexWriter indexWriter = null; IndexWriterConfig indexWriterConfig = new IndexWriterConfig( Version.LUCENE_35, analyzer); indexWriter = new IndexWriter( SimpleFSDirectory.open(new File(indexDir)), indexWriterConfig); for (int i = 0; i < htmls.length; i++) { String htmlPath = htmls[i].getAbsolutePath(); if (htmlPath.endsWith(".html") || htmlPath.endsWith(".htm")) { addDocument(htmlPath, indexWriter); } } indexWriter. indexWriter.close(); } public void addDocument(String htmlPath, IndexWriter indexWriter) throws IOException { HTMLDocParser htmlParser = new HTMLDocParser(htmlPath); String path = htmlParser.getPath(); String title = htmlParser.getTitle(); Reader content = new FileReader(new File(path)); //Reader content = htmlParser.getContent(); String contentStr = getContent(content);
Document document = new Document(); document.add(new Field("path", path, Field.Store.YES, Field.Index.NO)); document.add(new Field("title", title, Field.Store.YES, Field.Index.ANALYZED,Field.TermVector.YES)); document.add(new Field("content", contentStr, Field.Store.YES, Field.Index.ANALYZED,Field.TermVector.YES)); try { indexWriter.addDocument(document); } catch (IOException e) { e.printStackTrace(); } } |
分析上面的代码,首先需要一个analyzer ,它的作用是对文档中的文字进行分词,提取其中的pattern。
这里使用的是IKAnalyzer ,下面是它的介绍。可以从这里下载http://code.google.com/p/ik-analyzer/downloads/list
1.IK Analyzer 2012介绍 IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。 |
由于我们处理的中文数据,所以用开源的IKAnalyzer 来处理。其中可以选择它的智能输入法,或者最细切割法,来进行切词。
然后可以看到IndexWriter 初始化时候,需要指定index的存放目录。
其中Document 的概念是一个Document 代表一个文档的基本元素,一个Document中又可以包含多个Field,每个Field表示对doc中一类索引,在searcher时候,需要指定对一类field进行索引。
其中Filed又包含多个字段。
其构造函数如下:
可以看到,首先需要指定的是Filed的name,是自定义的一个字段。然后是value,就是需要进行索引的文本内容,然后是对filed的属性的选择,比如 Field.Store 表示对这个字段的value是否进行存储,对于小数据的value可以考虑存储。Field.Index里包含了对index时候的一些参数。Field.TermVector的主要作用是,是否存储在索引过程中一些算相关度的内部向量信息。
最后把相关信息填写好后,吧filed add 到 doc中,然后doc add 到 indexWriter中 。
至此,最简单的create index 就完成了。
接下来就是如何去search了。
先看一段代码:
IndexSearcher indexSearcher = null;
try {
Directory dir = new SimpleFSDirectory(new File( indexManager.getIndexDir())); indexSearcher = new IndexSearcher(IndexReader.open(dir)); } catch (IOException ioe) { ioe.printStackTrace(); }
QueryParser queryParser = new QueryParser(Version.LUCENE_35, "content", new IKAnalyzer(true));
Query query = null; try { query = queryParser.parse(searchWord); } catch (ParseException e) { e.printStackTrace(); } if (null != query && null != indexSearcher) { try { TopDocs hits = indexSearcher.search(query, 10); for (ScoreDoc sdoc : hits.scoreDocs) { Document doc = indexSearcher.doc(sdoc.doc); System.out.println(sdoc.score); System.out.println(doc.get("path")); System.out.println(doc.get("title")); //System.out.println(doc.get("content"));
} } catch (IOException e) { e.printStackTrace(); } } |
首先初始化IndexSearcher , 需要指定刚才的索引存储地址。
然后初始化 QueryParser queryParser = new QueryParser(Version.LUCENE_35, "content",
new IKAnalyzer(true));
指定需要索引的字段和Analyzer 。
query = queryParser.parse(searchWord);// 指定需要search 的文字字段。
通过indexSearcher.search(query, 10);// 返回满足条件的前10个doc。
至此就可以得到刚才进行索引的内容了。
Lucene很好的封装了建立索引和查询的过程,带来方便是不需要考虑太多细节。但是坏处是,如果自己
想控制其中的一些过程就会比较麻烦。其内部重要的一个部分是,制定了建立索引时候,对文本相关度进行计算的算法,
对每篇文档的filed进行了score,然后根据这个score来得到索引查询时候的rank。
现在介绍了这两个部分,就可以简单的对lucene的建立索引,和查询两个重要部分进行简单测试了。后面的文章在细节说明lucene中的一些高级的用法和实际的场景。