一、前言
在一般的结构化数据库中,一般去找一个字段的匹配,使用最多的就是like语句。这种情况下,就像在小时候妈妈给我买的新华字典里去一页页翻出自己的名字一样,效率相对的底下,较为快速的的方式是什么呢?就是通过新华字典的前面的索引来取找,而全文索引就是做的这样的一个工作。为你需要查找的"数据源"做各种的分析索引文件。这里的数据源可以是txt文件,图片文件等结构化的文件。而lucene是全文索引中比较优秀的第三方工具。
下载地址: http://apache.fayea.com/lucene/java/5.1.0/
现在最新的版本是5.1. 项目需要,本文操作的是3.5版本。
几乎所有的全文索引框架都会有这样几个组成
- 1.索引部分
- 2.分词部分
- 3.搜索部分
二、入门实践
初步了解lucene后,首先来直接入手一个demo,引入所需jar
操作环境:MyEclipse 10.0 jdk1.7
2.1 创建索引
package com.cfl.lucene;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
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.store.LockObtainFailedException;
import org.apache.lucene.util.Version;
public class LuceneHello {
public static void main(String[] args){
new LuceneHello().createIndex();
}
public void createIndex(){
//1.创建Directory
Directory directory=null;
IndexWriter writer=null;
Reader reader=null;
try {
//存放索引的硬盘位置
directory=FSDirectory.open(new File("E:\\Java\\lucene\\WP\\test02"));
} catch (IOException e) {
e.printStackTrace();
}
//2.创建indexWrite
try {
//配置指定的lucene版本及对应的分词器
IndexWriterConfig writerConfig=new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35));
writer=new IndexWriter(directory,writerConfig);
//需要被lucene创建索引的文件目录
File fs=new File("E:\\Java\\lucene\\WP\\testIndex");
Document doc=null;
//遍历文件目录下所有文件创建指定字段
for(File f:fs.listFiles()){
doc=new Document();
reader=new FileReader(f);
doc.add(new Field("name",f.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED));
doc.add(new Field("content",reader));
//3.写入索引字段到文件
writer.addDocument(doc);
}
System.out.println("索引创建成功");
} catch (CorruptIndexException e) {
System.out.println("索引创建失败!");
e.printStackTrace();
} catch (LockObtainFailedException e) {
System.out.println("索引创建失败!");
e.printStackTrace();
} catch (IOException e) {
System.out.println("索引创建失败!");
e.printStackTrace();
}finally{
//关闭writer对象
if(writer!=null){
try {
writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭reader对象
if(reader!=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
创建索引的基本步骤:
- 1.创建用于存放索引文件的Directory
- 2.创建用于写入索引文件夹IndexWrite
- 3.将创建索引写入document文件中
基本为以上三个步骤,能够按照三个步骤去将代码实现即可。当然会涉及到一些具体的细节,比如分词器的选择、是否存储、存储在硬盘还是内存等。在后面的文章中会一一分享。
2.2 搜索索引
public void searcher(){
//1.创建directory
try {
Directory dir=FSDirectory.open(new File("E:\\Java\\lucene\\WP\\testIndex\\index"));
//2.创建indexReader
IndexReader ireader=IndexReader.open(dir);
//3.根据indexReader创建searcher
IndexSearcher searcher=new IndexSearcher(ireader);
//4.创建query
QueryParser parser=new QueryParser(Version.LUCENE_35,"content",new StandardAnalyzer(Version.LUCENE_35));
//传入搜索的关键词
Query query=parser.parse("BEGIN");
//5.根据search搜索返回topdocs
TopDocs topDoc=searcher.search(query, 10);
//6.根据topdocs获取scoredoc对象
ScoreDoc[] sds=topDoc.scoreDocs;
//7.根据searcher和scoredoc对象获取具体的document对象
for(ScoreDoc sd:sds){
Document document=searcher.doc(sd.doc);
//8.根据document对象获取具体的值
System.out.println(document.get("filename")+document.get("path"));
}
} catch (IOException e) {
e.printStackTrace();
}
catch (ParseException e) {
e.printStackTrace();
}
}
针对搜索,相对简单。类似在jdbc的查询过程,创建query,为query指定关键词。
创建的得出的索引文件
其中大部分为分词文件,tii和tis为全部的数据文件,用于数据还原。详细的文件说明会后续说明。
FAQ:
调试日志
java.io.FileNotFoundException:E:\upload\construct\2014-07-16\7\index (拒绝访问。)
answer:
那是因为我的文件夹里套有文件夹导致的缘故。不能递归查找。所以对于文档和索引分开存放即可。