一 认识
- lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。
- 在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的xml或者大数据的字符类型。
lucene相关概念:
http://www.ibm.com/developerworks/cn/java/j-lo-lucene1/
下载lucene包(4.10版):
http://www.apache.org/dyn/closer.cgi/lucene/java/4.10.0
将下载后的压缩包解压后,将core和analysis目录下的jar包丢进项目path即可。
lucene4.10 API(学习如何使用)地址:
http://lucene.apache.org/core/4_10_0/core/index.html
比较完整的Lucene总结:
https://www.chedong.com/tech/lucene.html
非常详细的Lucene架构解说:
http://lucene.sourceforge.net/talks/pisa/
二 功能
- 获取内容(Acquire Content)
Lucene不提供爬虫功能,如果需要获取内容需要自己建立爬虫应用。
Lucene只做索引和搜索工作。 - 建立文档(Build Document)
文档通常由一个个域(fields)组成,例如:标题,正文,摘要等。
需要保证文档的格式一致(如都为txt格式),在此过程中可以通过语义分析来使要保存的文档更加精炼,也可以通过加权值来决定域和文档是否重要。可以再建立索引的时候加权值,也可以在搜索的时候加权值。 - 分析文档(Analyze Document)
解决如果控制符合单词,解决拼写错误,是否关联同义词,是否折叠单数复数形式。是否保留结果的偏差,当非拉丁语表示的语言,如何辨别词。 - 建立文档索引(Index Document)
- 搜索
支持单个或者符合查询,短语查询,通配符,模糊查询,结果排序
支持对错误拼写矫正等 - 建立查询(Build Query)
- 检索查询(Search Query)
- 返回结果(Rednder Results)
三 Lucene 软件包分析
Package: org.apache.lucene.document
这个包提供了一些为封装要索引的文档所需要的类,比如 Document, Field。这样,每一个文档最终被封装成了一个 Document 对象。
Package: org.apache.lucene.analysis
这个包主要功能是对文档进行分词,因为文档在建立索引之前必须要进行分词,所以这个包的作用可以看成是为建立索引做准备工作。
Package: org.apache.lucene.index
这个包提供了一些类来协助创建索引以及对创建好的索引进行更新。这里面有两个基础的类:IndexWriter 和 IndexReader,其中 IndexWriter 是用来创建索引并添加文档到索引中的,IndexReader 是用来删除索引中的文档的。
Package: org.apache.lucene.search
这个包提供了对在建立好的索引上进行搜索所需要的类。比如 IndexSearcher 和 Hits, IndexSearcher 定义了在指定的索引上进行搜索的方法,Hits 用来保存搜索得到的结果。
四 建立索引
为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:
Document
Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。
Field
Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。
Analyzer
在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。
常用分词器”
1.WhitespaceAnalyzer:仅仅是去掉了空格,没有其他任何操作,不支持中文。
2.SimpleAnalyzer:讲除了字母以外的符号全部去除,并且讲所有字符变为小写,需要注意的是这个分词器同样把数据也去除了,同样不支持中文。
3.StopAnalyzer:这个和SimpleAnalyzer类似,不过比他增加了一个的是,在其基础上还去除了所谓的stop words,比如the, a, this这些。这个也是不支持中文的。
4.StandardAnalyzer:英文方面的处理和StopAnalyzer一样的,对中文支持,使用的是单字切割。
5.CJKAnalyzer:这个支持中日韩,前三个字母也就是这三个国家的缩写。这个对于中文基本上不怎么用吧,对中文的支持很烂,它是用每两个字作为分割,分割方式个人感觉比较奇葩,我会在下面比较举例。
6.SmartChineseAnalyzer:中文的分词。比较标准的中文分词,对一些搜索处理的并不是很好
IndexWriter
IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。
Directory
这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。
public static void buildIndex(String idir,String dDir)throws IOException{
File indexDir = new File(idir);// 索引存放目录
File dataDir = new File(dDir);// 需要建立索引的文件目录
Analyzer luceneAnalyzer = new StandardAnalyzer();//分词工具
File[] dataFiles = dataDir.listFiles();
IndexWriterConfig indexConfig = new IndexWriterConfig(Version.LATEST, luceneAnalyzer);
FSDirectory fsDirectory = null;
IndexWriter indexWriter = null;
try {
fsDirectory = FSDirectory.open(indexDir);// 索引目录
indexWriter = new IndexWriter(fsDirectory, indexConfig);// 用于创建索引的对象
long startTime = new Date().getTime();
for (int i = 0; i < dataFiles.length; i++) {
if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".txt")) {
Document document = new Document();//代表一个文档
Reader txtReader = new FileReader(dataFiles[i]);
FieldType fieldType = new FieldType();
fieldType.setIndexed(true);
document.add(new TextField("path",dataFiles[i].getCanonicalPath(),Store.YES));//Field是用来描述文档的属性,比如这里文档设置了两个属性,路径和内容
document.add(new Field("contents", txtReader, fieldType));
indexWriter.addDocument(document);
}
}
indexWriter.commit();//为文档建立索引
long endTime = new Date().getTime();
System.out.println("It takes " + (endTime - startTime) + " milliseconds to create index for the files in directory " + dataDir.getPath());
} catch (IOException e) {
e.printStackTrace();
try {
indexWriter.rollback();
} catch (IOException e1) {
e1.printStackTrace();
}
} finally {
if(indexWriter!=null){
indexWriter.close();
}
}
}
五 搜索文档
利用 Lucene 进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引上进行搜索以找到包含某个关键词或短语的文档。Lucene 提供了几个基础的类来完成这个过程,它们分别是呢 IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。
Query
这是一个抽象类,他有多个实现,比如 TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query。
Term
Term 是搜索的基本单位,一个 Term 对象有两个 String 类型的域组成。生成一个 Term 对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个 Field 上进行查找,第二个参数代表了要查询的关键词。
TermQuery
TermQuery 是抽象类 Query 的一个子类,它同时也是 Lucene 支持的最为基本的一个查询类。生成一个 TermQuery 对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个 Term 对象。
IndexSearcher
IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。
Hits
Hits 是用来保存搜索的结果的。
public static void search(String queryStr) throws IOException {
File indexDir = new File("/home/luzhen/lucenceIndex");
FSDirectory fsDirectory = FSDirectory.open(indexDir);// 存放索引的目录
IndexReader indexReader = DirectoryReader.open(fsDirectory);
IndexSearcher searcher = new IndexSearcher(indexReader);
if (!indexDir.exists()) {
System.out.println("The Lucene index is not exist");
return;
}
Term term = new Term("contents", queryStr);//搜索的基本单位
TermQuery luceneQuery = new TermQuery(term);//基本的一个查询类
TopDocs doc = searcher.search(luceneQuery, 10);//使用query进行查询,10为限制返回的结果
for (int i = 0; i < doc.totalHits; i++) {//当有检索到结果时进入循环,打印出文档路径
Document docHit = searcher.doc(doc.scoreDocs[i].doc);
System.out.println(docHit.get("path"));
}
}
六 借鉴资料
lucene简介:http://www.chedong.com/tech/lucene.html
lucene入门系列:http://blog.csdn.net/column/details/jadyerlucene.html
lucene4新特性:
http://files.meetup.com/1446074/ImprovedSearchWithLucene4.pdf
http://blog.csdn.net/accesine960/article/details/8066877
lucene4重大升级:
http://blog.csdn.net/accesine960/article/details/6780068
lucene4:http://doc.okbase.net/qindongliang1922/archive/16465.html
lucene4.3与3.5性能对比:
http://www.cnblogs.com/seanvon/p/3173734.html
lucene4性能调优:
http://archive.apachecon.com/eu2012/presentations/06-Tuesday/PR-Lucene/aceu-2012-lucene-4-performance-tuning.pdf
lucene FST http://blog.mikemccandless.com/2010/12/using-finite-state-transducers-in.html
FSA算法 http://www.cs.nyu.edu/~mohri/pub/fla.pdf
lucene常用操作 http://www.wizzer.cn/?p=2299