最近在帮同学弄一个东西,无奈需要研究一下lucene,在这里笔记一下叨。大牛绕行……
一,环境搭配
下载lucene 2. 9.4 解压到任何一个地方。
然后在IDE中新建一个Java工程,将之前解压的文件夹下的lucene-core-2.9.4.jar 添加到库中。(工程右键属性,库,添加jar)
二,入门级例子及讲解
1)建立索引
为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:
Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。
Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。
Analyzer在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。
IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。
Directory这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。
熟悉了建立索引所需要的这些类后,我们就开始对某个目录下面的文本文件建立索引了:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package textfileindexer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
/** */ /**
* author lighter date 2006-8-7
*/
public class TextFileIndexer {
public static void main(String[] args) throws Exception {
/**/ /* 指明要索引文件夹的位置,这里是C盘的S文件夹下 */
File fileDir = new File( "D:\\luceneData" );
/**/ /* 这里放索引文件的位置 */
File indexDir = new File( "D:\\luceneIndex" );
Analyzer luceneAnalyzer = new StandardAnalyzer(); //建立一个标准分析器
IndexWriter indexWriter = new IndexWriter(indexDir, luceneAnalyzer,true ); //创建一个索引器
File[] textFiles = fileDir.listFiles();
long startTime = new Date().getTime();
//增加document到索引去
for ( int i = 0 ; i < textFiles.length; i ++ ) {
if (textFiles[i].isFile() && textFiles[i].getName().endsWith( ".txt" )) {
System.out.println( "File" + textFiles[i].getCanonicalPath()
+ "正在被索引." );
String temp = FileReaderAll(textFiles[i].getCanonicalPath(),"GBK" );
System.out.println(temp);
Document document = new Document(); //Document是一个记录。用来表示一个条目。就是搜索建立的倒排索引的条目。比如说,你要搜索自己电脑上的文件。这个时候就可以创建field。然后用field组合成 document 。最后会变成若干文件。这个document和 文件系统document不是一个概念。
Field FieldPath = new Field( "path" , textFiles[i].getPath(),Field.Store.YES, Field.Index.NO); //创建一个字段
Field FieldBody = new Field( "body" , temp, Field.Store.YES,Field.Index.TOKENIZED,Field.TermVector.WITH_POSITIONS_OFFSETS);
document.add(FieldPath);
document.add(FieldBody);
indexWriter.addDocument(document);
}
}
// optimize()方法是对索引进行优化
indexWriter.optimize();
indexWriter.close();
//测试一下索引的时间
long endTime = new Date().getTime();
System.out.println( "这花费了 "+ (endTime - startTime)+ " 毫秒来把文档增加到索引里面去! " + fileDir.getPath());
}
public static String FileReaderAll(String FileName, String charset)
throws IOException {
BufferedReader reader = new BufferedReader( new InputStreamReader(
new FileInputStream(FileName), charset));
String line = new String();
String temp = new String();
while ((line = reader.readLine()) != null ) {
temp += line;
}
reader.close();
return temp;
}
}
结果:
FileD:\luceneData\1.txt正在被索引.
中国中华人民共和国人民lucenelucenelucene
FileD:\luceneData\2.txt正在被索引.
lucene中国中华人民共和国人民lucenelucene
FileD:\luceneData\3.txt正在被索引.
lucenelucene中国中华人民共和国人民lucenelucene
这花费了 63 毫秒来把文档增加到索引里面去! D:\luceneData
2)搜索文档
利用 Lucene 进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引上进行搜索以找到包含某个关键词或短语的文档。Lucene 提供了几个基础的类来完成这个过程,它们分别是呢 IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。
Query这是一个抽象类,他有多个实现,比如 TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query。
Term 是搜索的基本单位,一个 Term 对象有两个 String 类型的域组成。生成一个 Term 对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个 Field 上进行查找,第二个参数代表了要查询的关键词。
TermQuery 是抽象类 Query 的一个子类,它同时也是 Lucene 支持的最为基本的一个查询类。生成一个 TermQuery 对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个 Term 对象。
IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。
Hits 是用来保存搜索的结果的。
介绍完这些搜索所必须的类之后,我们就开始在之前所建立的索引上进行搜索了:
package testquery;
import java.io.IOException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
public class TestQuery {
public static void main(String[] args) throws IOException, ParseException {
Hits hits = null ;
String queryString ="中国" ;
Query query = null ;
IndexSearcher searcher = new IndexSearcher( "D:\\luceneIndex" );
Analyzer analyzer = new StandardAnalyzer();
try{
QueryParser qp = new QueryParser( "body" , analyzer);
query = qp.parse(queryString);
} catch (ParseException e) {
}
if (searcher != null ) {
hits = searcher.search(query);
if (hits.length() >= 0 ) {
System.out.println( "找到: " + hits.length() + " 个结果! " );
}
}
}
}
运行结果:
找到: 3 个结果!
三,小例子测验
1)StandardAnalyzer
StandardAnalyzer是lucene中内置的"标准分析器",可以做如下功能:
1、对原有句子按照空格进行了分词
2、所有的大写字母都可以能转换为小写的字母
3、可以去掉一些没有用处的单词,例如"is","the","are"等单词,也删除了所有的标点
package standardanalyzertest;
import java.io.IOException;
import java.io.StringReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
public class StandardAnalyzerTest
{
//构造函数,
public StandardAnalyzerTest()
{
}
public static void main(String[] args)
{
//生成一个StandardAnalyzer对象
Analyzer aAnalyzer = new StandardAnalyzer();
//测试字符串
StringReader sr = new StringReader( " lighter javaeye com is the are on " );
//生成TokenStream对象
TokenStream ts = aAnalyzer.tokenStream( "name" , sr);
try {
int i = 0 ;
Token t = ts.next();
while (t != null )
{
//辅助输出时显示行号
i ++ ;
//输出处理后的字符
System.out.println( "第 " + i + "行: " + t.termText());
//取得下一个字符
t = ts.next();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
第 1行: lighter
第 2行: javaeye
第 3行: com
2)简单的简历索引并进行搜索的例子
package fsdirectorytest;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.FSDirectory;
public class FSDirectoryTest {
//建立索引的路径
public static final String path = "D:\\luceneIndex" ;
public static void main(String[] args) throws Exception {
Document doc1 = new Document();
doc1.add( new Field( "name" , "中国 javaeye com" ,Field.Store.YES,Field.Index.TOKENIZED));
Document doc2 = new Document();
doc2.add( new Field( "name" , "中国 blog" ,Field.Store.YES,Field.Index.TOKENIZED));
IndexWriter writer = new IndexWriter(FSDirectory.getDirectory(path, true ), new StandardAnalyzer(), true );
writer.setMaxFieldLength( 3 );
writer.addDocument(doc1);
writer.setMaxFieldLength( 3 );
writer.addDocument(doc2);
writer.close();
IndexSearcher searcher = new IndexSearcher(path);
Hits hits = null ;
Query query = null ;
QueryParser qp = new QueryParser( "name" , new StandardAnalyzer());
query = qp.parse( "中国" );
hits = searcher.search(query);
System.out.println( "查找 中国 共 " + hits.length() + "个结果 " );
query = qp.parse( "javaeye" );
hits = searcher.search(query);
System.out.println( "查找 javaeye 共 " + hits.length() + "个结果 " );
}
}