Lucene 4.5,document详解,例子实现,方法重写。
在这里分享一下Lucene的学习,主要参考官网上的一下教程和PDF版的《Lucene In Action》。当然,博客中很多内容都是摘自上面两个地方。
1. 什么是Lucene
Lucene是一个高性能的、可扩展的信息检索工具。你可以把它融入到应用程序中以增加索引和搜索功能。Lucene是一个纯Java实现的成熟、自由、开源的软件项目。
它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。
官方网站:http://lucene.apache.org/
CSDN下载地址:http://download.csdn.net/detail/jolingogo/6472385
2. 索引和搜索
使用Lucene,需要理解索引和搜索这两个概念。
索引:为了快速搜索大量文本文件,首先必须为文件建立索引,就像为一本书建立目录,然后把文本转换成你能够快速搜索到的格式,
而不是使用那种慢速顺序扫描的处理法。这个转换过程就叫做索引操作(indexing),他的输出就称为索引文件(index)。
可以把索引想象成一种数据结构,这种数据结构允许对存储在其中的单词进行快速随机存取。
搜索:是在一个索引中查找关键字的过程,这个过程的目的是为了找到这些关键字在哪些地方出现过。
搜索的质量通常有查确率(precise)和查全率(recall)来衡量。查全率可以衡量这个搜索系统查找到相关文档的能力,
而查确率则是用来衡量搜索系统过滤非相关文档的能力。
3. 第一个示例
准备工作:
1.新建2个文件夹
Lucene_data 里面,我新建了几个txt文本文件
Lucene_index用来存放索引
2. pom.xml
<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>org.ygy</groupId> <artifactId>lucene</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>lucene</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <!-- Lucene依赖包 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>4.5.1</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-icu</artifactId> <version>4.5.1</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queryparser</artifactId> <version>4.5.1</version> </dependency> </dependencies> </project>
3.1 建立索引
- package org.ygy.lucene;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- 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.document.LongField;
- import org.apache.lucene.document.StringField;
- import org.apache.lucene.document.TextField;
- import org.apache.lucene.index.IndexWriter;
- import org.apache.lucene.index.IndexWriterConfig;
- import org.apache.lucene.index.Term;
- import org.apache.lucene.store.Directory;
- import org.apache.lucene.store.FSDirectory;
- import org.apache.lucene.util.Version;
- /**
- * 建立索引
- *
- * @author yuguiyang
- *
- */
- public class IndexFiles {
- // -index F:\Lucene_index -docs F:\Lucene_data
- public static void main(String[] args) {
- String usage = "java org.apache.lucene.demo.IndexFiles [-index INDEX_PATH] [-docs DOCS_PATH] [-update]\n\nThis indexes the documents in DOCS_PATH, creating a Lucene indexin INDEX_PATH that can be searched with SearchFiles";
- String indexPath = "index"; // 索引存放的路径
- String docsPath = null; // 需要给哪些文件建立索引(即资源库的地址)
- boolean create = true; // 是否新建索引
- for (int i = 0; i < args.length; i++) {
- if ("-index".equals(args[i])) {
- indexPath = args[(i + 1)];
- i++;
- } else if ("-docs".equals(args[i])) {
- docsPath = args[(i + 1)];
- i++;
- } else if ("-update".equals(args[i])) {
- create = false;
- }
- }
- if (docsPath == null) {
- System.err.println("Usage: " + usage);
- System.exit(1);
- }
- // 验证资源文件地址
- File docDir = new File(docsPath);
- if ((!docDir.exists()) || (!docDir.canRead())) {
- System.out.println("Document directory '" + docDir.getAbsolutePath()
- + "' does not exist or is not readable, please check the path");
- System.exit(1);
- }
- // 开始建立索引
- Date start = new Date();
- try {
- System.out.println("Indexing to directory '" + indexPath + "'...");
- // 根据索引存放地址,创建目录
- Directory dir = FSDirectory.open(new File(indexPath));
- // 初始化分析器
- Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_45);
- //索引配置
- IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_45, analyzer);
- if (create) {
- iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
- } else {
- iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
- }
- //初始化索引
- 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());
- }
- }
- //递归的方式,遍历每一个文件
- static void indexDocs(IndexWriter writer, File file) throws IOException {
- if (file.canRead())
- if (file.isDirectory()) {
- String[] files = file.list();
- if (files != null)
- for (int i = 0; i < files.length; i++)
- indexDocs(writer, new File(file, files[i]));
- } else {
- FileInputStream fis;
- try {
- fis = new FileInputStream(file);
- } catch (FileNotFoundException fnfe) {
- return;
- }
- try {
- Document doc = new Document();
- Field pathField = new StringField("path", file.getPath(), Field.Store.YES);
- doc.add(pathField);
- doc.add(new LongField("modified", file.lastModified(), Field.Store.NO));
- doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(fis, "UTF-8"))));
- if (writer.getConfig().getOpenMode() == IndexWriterConfig.OpenMode.CREATE) {
- System.out.println("adding " + file);
- writer.addDocument(doc);
- } else {
- System.out.println("updating " + file);
- writer.updateDocument(new Term("path", file.getPath()), doc);
- }
- } finally {
- fis.close();
- }
- }
- }
- }
好了,虽然,上面的代码还不是很明白,但是,运行一下先。
运行时,需要指定一些参数:
运行结果:
好了,索引建立成功了,看一下,F:\Lucene_index文件夹
这些文件具体是什么,不太清楚,暂且当做是索引文件吧。
3.2 搜索
- package org.ygy.lucene;
- 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.index.DirectoryReader;
- import org.apache.lucene.index.IndexReader;
- import org.apache.lucene.queryparser.classic.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.FSDirectory;
- import org.apache.lucene.util.Version;
- public class SearchFiles {
- public static void main(String[] args) throws Exception {
- //对参数的一些处理
- String usage = "Usage:\tjava org.apache.lucene.demo.SearchFiles [-index dir] [-field f] [-repeat n] [-queries file] [-query string] [-raw] [-paging hitsPerPage]\n\nSee http://lucene.apache.org/core/4_1_0/demo/ for details.";
- if ((args.length > 0) && (("-h".equals(args[0])) || ("-help".equals(args[0])))) {
- System.out.println(usage);
- System.exit(0);
- }
- String index = "index";
- String field = "contents";
- String queries = null;
- int repeat = 0;
- boolean raw = false;
- String queryString = null;
- int hitsPerPage = 10;
- for (int i = 0; i < args.length; i++) {
- if ("-index".equals(args[i])) {
- index = args[(i + 1)];
- i++;
- } else if ("-field".equals(args[i])) {
- field = args[(i + 1)];
- i++;
- } else if ("-queries".equals(args[i])) {
- queries = args[(i + 1)];
- i++;
- } else if ("-query".equals(args[i])) {
- queryString = args[(i + 1)];
- i++;
- } else if ("-repeat".equals(args[i])) {
- repeat = Integer.parseInt(args[(i + 1)]);
- i++;
- } else if ("-raw".equals(args[i])) {
- raw = true;
- } else if ("-paging".equals(args[i])) {
- hitsPerPage = Integer.parseInt(args[(i + 1)]);
- if (hitsPerPage <= 0) {
- System.err.println("There must be at least 1 hit per page.");
- System.exit(1);
- }
- i++;
- }
- }
- //读取索引
- IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(index)));
- //查询索引
- IndexSearcher searcher = new IndexSearcher(reader);
- //分析器
- Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_45);
- BufferedReader in = null;
- if (queries != null)
- in = new BufferedReader(new InputStreamReader(new FileInputStream(queries), "UTF-8"));
- else {
- in = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
- }
- //解析器
- QueryParser parser = new QueryParser(Version.LUCENE_45, field, analyzer);
- while (true) {
- if ((queries == null) && (queryString == null)) {
- 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));
- if (repeat > 0) {
- Date start = new Date();
- for (int i = 0; i < repeat; i++) {
- searcher.search(query, null, 100);
- }
- Date end = new Date();
- System.out.println("Time: " + (end.getTime() - start.getTime()) + "ms");
- }
- doPagingSearch(in, searcher, query, hitsPerPage, raw, (queries == null) && (queryString == null));
- if (queryString != null) {
- break;
- }
- }
- reader.close();
- }
- public static void doPagingSearch(BufferedReader in, IndexSearcher searcher, Query query, int hitsPerPage,
- boolean raw, boolean interactive) throws IOException {
- TopDocs results = searcher.search(query, 5 * hitsPerPage);
- ScoreDoc[] hits = results.scoreDocs;
- int numTotalHits = results.totalHits;
- System.out.println(numTotalHits + " total matching documents");
- int start = 0;
- int end = Math.min(numTotalHits, hitsPerPage);
- while (true) {
- if (end > hits.length) {
- System.out.println("Only results 1 - " + hits.length + " of " + numTotalHits
- + " total matching documents collected.");
- System.out.println("Collect more (y/n) ?");
- String line = in.readLine();
- if ((line.length() == 0) || (line.charAt(0) == 'n')) {
- break;
- }
- hits = searcher.search(query, numTotalHits).scoreDocs;
- }
- end = Math.min(hits.length, start + hitsPerPage);
- for (int i = start; i < end; i++) {
- if (raw) {
- System.out.println("doc=" + hits[i].doc + " score=" + hits[i].score);
- } else {
- Document doc = searcher.doc(hits[i].doc);
- String path = doc.get("path");
- if (path != null) {
- System.out.println(i + 1 + ". " + path);
- String title = doc.get("title");
- if (title != null)
- System.out.println(" Title: " + doc.get("title"));
- } else {
- System.out.println(i + 1 + ". " + "No path for this document");
- }
- }
- }
- if ((!interactive) || (end == 0)) {
- break;
- }
- if (numTotalHits >= end) {
- boolean quit = false;
- while (true) {
- System.out.print("Press ");
- if (start - hitsPerPage >= 0) {
- System.out.print("(p)revious page, ");
- }
- if (start + hitsPerPage < numTotalHits) {
- System.out.print("(n)ext page, ");
- }
- System.out.println("(q)uit or enter number to jump to a page.");
- String line = in.readLine();
- if ((line.length() == 0) || (line.charAt(0) == 'q')) {
- quit = true;
- break;
- }
- if (line.charAt(0) == 'p') {
- start = Math.max(0, start - hitsPerPage);
- break;
- }
- if (line.charAt(0) == 'n') {
- if (start + hitsPerPage >= numTotalHits)
- break;
- start += hitsPerPage;
- break;
- }
- int page = Integer.parseInt(line);
- if ((page - 1) * hitsPerPage < numTotalHits) {
- start = (page - 1) * hitsPerPage;
- break;
- }
- System.out.println("No such page");
- }
- if (quit)
- break;
- end = Math.min(numTotalHits, start + hitsPerPage);
- }
- }
- }
- }
哎,到目前为止,对上面的程序还不是很理解,但是可以跑通了,还不错,接着学习一下。
运行后,会提示,让你输入要查找的内容:
好了,目前之理解了这么多,先学一会儿,再接着分享哈。
本文介绍 Lucene 4.5 的基本概念,包括如何为文档建立索引和搜索索引文件。通过实际代码示例展示了如何使用 Java API 创建索引,并演示了如何查询已建立的索引。
&spm=1001.2101.3001.5002&articleId=33330241&d=1&t=3&u=c922a58c4b4b4622b69be7cc4577698f)
7538

被折叠的 条评论
为什么被折叠?



