您的位置:首页 > 其它

Lucene 快速入门

2016-05-16 14:30 525 查看

Lucene 简介

Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。

Lucene 6.0.0 demo API

要想快速入门最快的学习方法就是看官方 demo 文档。

所需要的 jar 包:

lucene-core-{version}.jar

lucene-queryparser-{version}.jar

lucene-analyzers-common-{version}.jar

lucene-demo-{version}.jar

建立索引

全文搜索之所以如此的迅速就是因为搜索是在索引库中进行,将所需搜索的内容建立索引并以文件的形式保存。

Lucene 提供了五个基本类来建立索引:

Document

Document 是用来描述文档的,一个 Document 对象由多个 Field 对象组成。

Field

Field 对象是用来描述文档的某个属性的。可以把一个 Document 对象比喻成数据库中的一条记录,Field 是这个记录的字段,例如一个 File 对象的路径和文本内容可以用两个 Field 对象分别描述。

Analyzer

分词器。在一个文档被索引之前,首先需要对文档内容进行分词处理。

IndexWriter

IndexWriter 是 Lucene 用来创建索引的一个核心类,它的作用是把一个个的 Document 对象加到索引库中来。

Directory

处理索引的存储位置。

样例 IndexFiles.java 对文本文档建立索引。

public static void main(String[] args) {
// 索引存放目录
String indexPath = "index";

String docsPath = "需要索引的目录";
final Path docDir = Paths.get(docsPath);
Date start = new Date();
try {
System.out.println("Indexing to directory '" + indexPath + "'...");

Directory dir = FSDirectory.open(Paths.get(indexPath));
Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
IndexWriter writer = new IndexWriter(dir, iwc);

indexDocs(writer, docDir);

writer.close();

Date end = new Date();
System.out.println(end.getTime() - start.getTime() + " total milliseconds");

} catch (IOException e) {
System.out.println(" caught a " + e.getClass() +
"\n with message: " + e.getMessage());
}
}
/**
* 对每个文件进行索引
* @param writer 存储索引
* @param path 需要索引的文件或目录
* /
static void indexDocs(final IndexWriter writer, Path path) throws IOException {
// 如果是目录就遍历
if (Files.isDirectory(path)) {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
try {
indexDoc(writer, file, attrs.lastModifiedTime().toMillis());
} catch (IOException ignore) {
// 如果文件不能读取不影响下一个文件的索引
}
return FileVisitResult.CONTINUE;
}
});
} else {
indexDoc(writer, path, Files.getLastModifiedTime(path).toMillis());
}
}
/**
* 设置索引内容
*/
static void indexDoc(IndexWriter writer, Path file, long lastModified) throws IOException {
try (InputStream stream = Files.newInputStream(file)) {
Document doc = new Document();
// 构造器 StringField(String name, String value, Field.Store stored)
// StringField 索引但不分词, 也就是会把这个字符串当成一个完整的词来进行索引.
// Field.Store 是否存储
Field pathField = new StringField("path", file.toString(), Field.Store.YES);
doc.add(pathField);
// 构造器 TextField(String name, Reader reader)
// TextField 索引分词
doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));
// OpenMode.CREATE  创建新索引或覆盖已有索引
// OpenMode.CREATE_OR_APPEND 将索引添加进已有索引, 如果不存在旧索引就创建新索引
if (writer.getConfig().getOpenMode() == OpenMode.CREATE) {
System.out.println("adding " + file);
writer.addDocument(doc);
} else {
System.out.println("updating " + file);
writer.updateDocument(new Term("path", file.toString()), doc);
}
}
}


搜索

文本文档建立好索引后,就可以在索引上进行搜索啦。

Lucene 提供了四个基本类来进行搜索:

IndexSearch

IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。

Query

这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query。

TopDocs

存储 IndexSearcher.search(Query,int) 返回的结果集。

ScoreDoc

将 TopDocs 数据处理成所需的 hits。

样例 SearchFiles.java 进行搜索

public static void main(String[] args) throws Exception {
// 索引目录
String index = "index";
// 要搜索的字段
String field = "contents";
String queries = null;
String queryString = null;
// 需要显示的结果数
int hitsPerPage = 10;

IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(index)));
IndexSearcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new StandardAnalyzer();

BufferedReader in = null;
in = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));

QueryParser parser = new QueryParser(field, analyzer);
while (true) {
if (queries == null && queryString == null) {                        // prompt the user
System.out.println("Enter query: ");
}

String line = queryString != null ? queryString : in.readLine();

if (line == null || line.length() == -1) {
break;
}

line = line.trim();
if (line.length() == 0) {
break;
}

Query query = parser.parse(line);
System.out.println("Searching for: " + query.toString(field));
TopDocs results = searcher.search(query, hitsPerPage);
ScoreDoc[] hits = results.scoreDocs;
int numTotalHits = results.totalHits;
System.out.println(numTotalHits + " total matching documents");
for(int i=0;i<hits.lengt
a3c3
h;i++){
Document doc = searcher.doc(hits[i].doc);
System.out.println(doc.get("path"));
}

if (queryString != null) {
break;
}
}
reader.close();
}


以上是对文本内容进行搜索,如果需要搜索目录,只需修改 Document 和 Field

// 构造器 TextField(String name, String value, Field.Store store)
doc.add(new TextField("path",file.toString(),Field.Store.YES));
String field = "path";
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: