lucene入门篇
2017-09-27 00:00
246 查看
最近由于一个项目用到了搜索,研究了lucene,把我的学习经过总结一下,希望大家少走弯路。
luncene基本概念:
lucence是一个很容易上手,纯java语言的全文索引检索工具包。
Lucene的作者是资深的全文索引/检索专家,最开始发布在他本人的主页上,2001年10月贡献给APACHE,成为APACHE基金jakarta的一个子项目。
目前,lucene广泛用于全文索引/检索的项目中。
Lucene 原理
lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。
在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的 时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的 xml或者大数据的字符类型。
全文检索的实现机制
Lucene的API接口设计的比较通用,输入输出结构都很像数据库的表==>记录==>字段,所以很多传统的应用的文件、数据库等都可以比较方便的映射到Lucene的存储结构/接口中。总体上看:可以先把Lucene当成一个支持全文索引的数据库系统 。
Lucene作为一个全文检索引擎,其具有如下突出的优点:
(1)索引文件格式独立于应用平台。 Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。
(
2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引 ,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。
(3)优秀的面向对象的系统架构 ,使得对于Lucene扩展的学习难度降低,方便扩充新功能。
(4)设计了独立于语言和文件格式的文本分析接口 ,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。
(5)已经默认实现了一套强大的查询引擎 ,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询(Fuzzy Search[11])、分组查询等等。
建立索引
为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:
Document
Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。
Field
Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。
Analyzer
在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。
IndexWriter
IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。
Directory
这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。
熟悉了建立索引所需要的这些类后,我们就开始对某个目录下面的文本文件建立索引了,清单1给出了对某个目录下的文本文件建立索引的源代码:
搜索文档
利用Lucene进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引 上进行搜索以找到包含某个关键词或短语的文档。Lucene提供了几个基础的类来完成这个过程,它们分别是呢IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。
Query
这是一个抽象类,他有多个实现,比如TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成Lucene能够识别的Query。
Term
Term是搜索的基本单位,一个Term对象有两个String类型的域组成。生成一个Term对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个Field上进行查找,第二个参数代表了要查询的关键词。
TermQuery
TermQuery是抽象类Query的一个子类,它同时也是Lucene支持的最为基本的一个查询类。生成一个TermQuery对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个Term对象。
IndexSearcher
IndexSearcher是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个IndexSearcher的实例在一个索引上进行操作。
Hits
Hits是用来保存搜索的结果的。
在系统的D盘的User文件夹里建两个文件夹index,file,file里新建几个文本文件1.txt,2.txt...名字可以随意起,在每个文本里写上一句话保存为utf-8格式 这个特别重要,不然搜索的时候会查找不到结果下面是建立索引的类
下面是搜索的类
下面是路径类
luncene基本概念:
lucence是一个很容易上手,纯java语言的全文索引检索工具包。
Lucene的作者是资深的全文索引/检索专家,最开始发布在他本人的主页上,2001年10月贡献给APACHE,成为APACHE基金jakarta的一个子项目。
目前,lucene广泛用于全文索引/检索的项目中。
Lucene 原理
lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。
在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的 时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的 xml或者大数据的字符类型。
全文检索的实现机制
Lucene的API接口设计的比较通用,输入输出结构都很像数据库的表==>记录==>字段,所以很多传统的应用的文件、数据库等都可以比较方便的映射到Lucene的存储结构/接口中。总体上看:可以先把Lucene当成一个支持全文索引的数据库系统 。
Lucene作为一个全文检索引擎,其具有如下突出的优点:
(1)索引文件格式独立于应用平台。 Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。
(
2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引 ,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。
(3)优秀的面向对象的系统架构 ,使得对于Lucene扩展的学习难度降低,方便扩充新功能。
(4)设计了独立于语言和文件格式的文本分析接口 ,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。
(5)已经默认实现了一套强大的查询引擎 ,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询(Fuzzy Search[11])、分组查询等等。
建立索引
为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:
Document
Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。
Field
Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。
Analyzer
在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。
IndexWriter
IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。
Directory
这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。
熟悉了建立索引所需要的这些类后,我们就开始对某个目录下面的文本文件建立索引了,清单1给出了对某个目录下的文本文件建立索引的源代码:
搜索文档
利用Lucene进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引 上进行搜索以找到包含某个关键词或短语的文档。Lucene提供了几个基础的类来完成这个过程,它们分别是呢IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。
Query
这是一个抽象类,他有多个实现,比如TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成Lucene能够识别的Query。
Term
Term是搜索的基本单位,一个Term对象有两个String类型的域组成。生成一个Term对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个Field上进行查找,第二个参数代表了要查询的关键词。
TermQuery
TermQuery是抽象类Query的一个子类,它同时也是Lucene支持的最为基本的一个查询类。生成一个TermQuery对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个Term对象。
IndexSearcher
IndexSearcher是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个IndexSearcher的实例在一个索引上进行操作。
Hits
Hits是用来保存搜索的结果的。
在系统的D盘的User文件夹里建两个文件夹index,file,file里新建几个文本文件1.txt,2.txt...名字可以随意起,在每个文本里写上一句话保存为utf-8格式 这个特别重要,不然搜索的时候会查找不到结果下面是建立索引的类
package test3; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Date; 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; public class LuceneIndexTest { public static void main(String[] args) throws Exception { // 声明一个对象 LuceneIndexTest indexer = new LuceneIndexTest(); // 建立索引 Date start = new Date(); indexer.writeToIndex(); Date end = new Date(); System.out.println("建立索引用时" + (end.getTime() - start.getTime()) + "毫秒"); indexer.close(); } public LuceneIndexTest() { try { writer = new IndexWriter(Constants.INDEX_STORE_PATH, new StandardAnalyzer(), true); } catch (Exception e) { e.printStackTrace(); } } // 索引器 private IndexWriter writer = null; // 将要建立索引的文件构造成一个Document对象,并添加一个域"content" private Document getDocument(File f) throws Exception { Document doc = new Document(); FileInputStream is = new FileInputStream(f); Reader reader = new BufferedReader(new InputStreamReader(is)); doc.add(Field.Text("contents", reader)); doc.add(Field.Keyword("path", f.getAbsolutePath())); return doc; } public void writeToIndex() throws Exception { File folder = new File(Constants.INDEX_FILE_PATH); if (folder.isDirectory()) { String[] files = folder.list(); for (int i = 0; i < files.length; i++) { File file = new File(folder, files[i]); Document doc = getDocument(file); System.out.println("正在建立索引 : " + file + ""); writer.addDocument(doc); } } } public void close() throws Exception { writer.close(); } }
下面是搜索的类
package test3; import java.util.Date; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; 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 LuceneSearchTest { public static void main(String[] args) throws Exception { LuceneSearchTest test = new LuceneSearchTest(); Hits h = null; h = test.search("法院"); test.printResult(h); h = test.search("学院"); test.printResult(h); h = test.search("boy"); test.printResult(h); } public LuceneSearchTest() { try { searcher = new IndexSearcher(IndexReader .open(Constants.INDEX_STORE_PATH)); } catch (Exception e) { e.printStackTrace(); } } // 声明一个IndexSearcher对象 private IndexSearcher searcher = null; // 声明一个Query对象 private Query query = null; public final Hits search(String keyword) { System.out.println("正在检索关键字 : " + keyword); try { // 将关键字包装成Query对象 query = QueryParser.parse(keyword, "contents", new StandardAnalyzer()); Date start = new Date(); Hits hits = searcher.search(query); Date end = new Date(); System.out.println("检索完成,用时" + (end.getTime() - start.getTime()) + "毫秒"); return hits; } catch (Exception e) { e.printStackTrace(); return null; } } public void printResult(Hits h) { if (h.length() == 0) { System.out.println("对不起,没有找到您要的结果。"); } else { for (int i = 0; i < h.length(); i++) { try { Document doc = h.doc(i); System.out.print("这是第" + i + "个检索到的结果,文件名为:"); System.out.println(doc.get("path")); } catch (Exception e) { e.printStackTrace(); } } } System.out.println("--------------------------"); } }
下面是路径类
package test1; public class Constants { public final static String INDEX_FILE_PATH = "d:\\Users\\file"; public final static String INDEX_STORE_PATH = "d:\\Users\\index"; }lucene与数据库的对比
Lucene | 数据库 |
索引数据源:doc(field1,field2...) doc(field1,field2...) \ indexer / _____________ | Lucene Index| -------------- / searcher \ 结果输出:Hits(doc(field1,field2) doc(field1...)) | 索引数据源:record(field1,field2...) record(field1..) \ SQL: insert/ _____________ | DB Index | ------------- / SQL: select \ 结果输出:results(record(field1,field2..) record(field1...)) |
Document:一个需要进行索引的“单元” 一个Document由多个字段组成 | Record:记录,包含多个字段 |
Field:字段 | Field:字段 |
Hits:查询结果集,由匹配的Document组成 | RecordSet:查询结果集,由多个Record组成 |
相关文章推荐
- Lucene入门
- Lucene入门项目实例---比较Lucene方式搜索与传统String方式搜索的效率
- Lucene搜索引擎入门写法
- Lucene安装及入门
- Lucene入门与使用(三) [转]
- 【Lucene】Apache Lucene全文检索引擎架构之入门实战1
- java lucene入门例子
- Lucene 快速入门
- lucene简单入门demo
- Lucene入门的基本知识(一)
- lucene第一步--简单的入门demo
- Lucene 6.1.0 入门Demo
- Lucene入门教程
- Lucene入门教程03
- Lucene 3.6.2入门:自定义停用词分词器和同义词分词器
- lucene入门学习
- lucene4入门(3)琐记
- Lucene入门实例
- Lucene 入门示例
- lucene入门教程