简介
Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。(摘自百度百科)
代码环境
操作系统:centos 5.8
开发环境:Eclipse 4.3
构建工具:Maven 4.0
Maven配置
为了能够按照书中的例子进行学习,这里依赖的Lucene版本是3.0.1
<dependencies>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>3.0.1</version>
</dependency>
</dependencies>
完整配置:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.linjl.study.book</groupId>
<artifactId>book_luceneInAction</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source />
<target />
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>3.0.1</version>
</dependency>
</dependencies>
</project>
程序示例
下面将用两个例子进行Lucene入门讲解
案例一:建立索引
案例一主要展示通过对指定路径下.txt文件建立索引的过程
完整源码:
package com.linjl.study.book.luceneInAction.chapter1;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
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.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
public class Indexer {
private IndexWriter indexWriter;
public Indexer(String indexDir) throws IOException {
//步骤一:创建 Directory
Directory dir = FSDirectory.open(new File(indexDir));
//步骤二:创建 IndexWriter
indexWriter = new IndexWriter(dir, new StandardAnalyzer(
Version.LUCENE_30), true, IndexWriter.MaxFieldLength.UNLIMITED);
}
public void close() throws CorruptIndexException, IOException {
//步骤五:关闭IndexWriter
indexWriter.close();
}
public int index(String dataDir, FileFilter fileFilter) throws IOException {
File[] files = new File(dataDir).listFiles();
for (File file : files) {
if (!file.isDirectory() && !file.isHidden() && file.exists()
&& file.canRead()
&& (fileFilter == null || fileFilter.accept(file))) {
indexFile(file);
}
}
return indexWriter.numDocs();
}
private void indexFile(File file) throws IOException {
System.out.println("Indexing " + file.getCanonicalPath());
//步骤三:创建Document对象
Document doc = getDocument(file);
//步骤四:添加Document
indexWriter.addDocument(doc);
}
protected Document getDocument(File file) throws IOException {
Document doc = new Document();
doc.add(new Field("contents", new FileReader(file)));
doc.add(new Field("filename", file.getName(), Field.Store.YES,
Field.Index.NOT_ANALYZED));
doc.add(new Field("fullpath", file.getCanonicalPath(), Field.Store.YES,
Field.Index.NOT_ANALYZED));
return doc;
}
private static class TextFilesFilter implements FileFilter {
public boolean accept(File pathname) {
return pathname.getName().toLowerCase().endsWith(".txt");
}
}
public static void main(String[] strs) throws IOException {
//存放索引的位置(linux环境下路径)
String indexDir = "/opt/test/lucene/index";
//存放待索引文件的位置(linux环境下路径)
String dataDir = "/opt/test/lucene/files";
long startTime = System.currentTimeMillis();
Indexer indexer = new Indexer(indexDir);
int numIndexed;
try {
numIndexed = indexer.index(dataDir, new TextFilesFilter());
} finally {
indexer.close();
}
long endTime = System.currentTimeMillis();
System.out.println("Indexing " + numIndexed + " files took "
+ (endTime - startTime) + "ms");
}
}
案例二:搜索索引
案例二展示如何通过对指定的索引文件夹进行关键词索引
完整源码:
package com.linjl.study.book.luceneInAction.chapter1;
import java.io.File;
import java.io.IOException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.ParseException;
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.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
public class Searcher {
public static void search(String indexDir, String searchWord)
throws IOException, ParseException {
//步骤一:创建Directory
Directory dir = FSDirectory.open(new File(indexDir));
//步骤二:创建IndexSearcher
IndexSearcher indexSearcher = new IndexSearcher(dir);
//步骤三:创建QueryParser
QueryParser parser = new QueryParser(Version.LUCENE_30, "contents",
new StandardAnalyzer(Version.LUCENE_30));
long startTime = System.currentTimeMillis();
//步骤四:解析生成查询对象
Query query = parser.parse(searchWord);
//步骤五:查询并获取查询结果(只是获取到查询结果的引用)
TopDocs hits = indexSearcher.search(query, 30);
long endTime = System.currentTimeMillis();
System.out.println("Found " + hits.totalHits + "document(s) (in "
+ (endTime - startTime) + "ms) that matched query '"
+ searchWord + "':");
for (ScoreDoc scoreDoc : hits.scoreDocs) {
//步骤六:根据引用生成查询结果
Document doc = indexSearcher.doc(scoreDoc.doc);
System.out.println(doc.get("fullpath"));
}
//步骤七:关闭IndexSearcher
indexSearcher.close();
}
public static void main(String[] args) throws IOException, ParseException {
String indexDir = "/opt/test/lucene/index";
String searchWord = "床";
Searcher.search(indexDir, searchWord);
}
理解建立索引过程的核心类
- IndexWriter
IndexWriter(写索引)是索引过程的核心组件。这个类负责创建新索引或者打开已有索引,以及向索引添加、删除或者更新文档的信息。他只能写入索引不能读取或者搜索索引。 - Directory
Directory描述了Lucene索引存放的位置。它是一个抽象类,有很多子类,例子中的FsDirectory是基于文件系统的索引,还有基于内存等更多子类。 - Analyzer
文本文件在被索引或者建立索引的时候都需要经过Analyzer(分析器)处理。它负责从被索引文本文件中提取语汇单元,并提出剩下的无用信息。Analyzer是一个抽象类,Lucene提供了几个实现类,不过对中文分词的效果不太好,网上有几个比较好的开源中文分词库IKAnalyzer,mmseg - Document
Document(文档)对象代表一些域(Field)的集合。你可以将Document理解为虚拟文档—比如Web页面、E-mail信息或者文本文件---然后你可以从中取回大量的数据。 - Field
索引中的每个文档都包含一个或多个不同命名的域,这些鱼包含在Field类中,每个域都有一个域名和对应的域值,以及一组选项来精确控制Lucene索引操作各个域值。文档可能拥有不值一个同名的域。在这种情况下,域的值就按照索引操作顺序添加进去。在搜索时,所有域的文本就好像连接在一起,作为一个文本域来处理。
理解搜索过程的核心类
- IndexSearcher
IndexSearcher类用于搜索由IndexWriter类创建的索引:这个类公开了几个搜索的方法,他是链接索引的中间环节,可以将IndexSearcher类看作是一个以只读方式打开索引的类。它需要利用Direcotry实例来控制前期创建的索引,然后才能提供大量的搜索方法。该类最简单的用法如下:Directory dir = FSDirectory.open(new File("/tmp/index")); IndexSearcher searcher = new IndexSearcher(dir); Query q = new TermQuery(new Term("contents","lucene")); TopDocs hits = searcher.search(q,10); searcher.close();
- Term
Term对象是搜索功能的基本单元,与Field对象类似,Term对象包含一对字符串元素:域名和单词。 - Query
Lucene含有许多具体的Query(查询)子类。 - TermQuery
TermQuery是Lucene提供的最基本的查询类型,也是简单查询类型之一。 - TopDocs
TopDocs类是一个简单的指针容器,指针一般指向前N个排名的搜索结果,搜索结果即匹配查询条件的文档。TopDocs会记录前N个结果中每个结果的int docID(可以用它来回复文档)和浮点型分数
小结
本文主要是Lucene In Action 第一章的内容,通过2个例子,对lucene有了最初的认识和使用方法。
(全文完 linjl 20130904 深圳)
来源:oschina
链接:https://my.oschina.net/u/1021915/blog/159000