Lucene4.9学习笔记——Lucene建立索引

基本上创建索引需要三个步骤:

1、创建索引库IndexWriter对象

2、根据文件创建文档Document

3、向索引库中写入文档内容

这其中主要涉及到了IndexWriter(索引的核心组件,用于创建或追加索引)、Document(代表一些域Field的集合)、Field(具体的域,如文档创建时间、作者、内容等)、Analyzer(分词器)、Directory(用于描述索引存放位置)这些主要的类。

我们参照上一节的代码来看建立索引。

1、创建IndexWriter

// 索引文件的保存位置
      Directory dir = FSDirectory.open(new File(indexStorePath));
      // 分析器
      Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_4_9);
      // 配置类
      IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_4_9, analyzer);
      iwc.setOpenMode(OpenMode.CREATE);// 创建模式 OpenMode.CREATE_OR_APPEND 添加模式
      IndexWriter writer = new IndexWriter(dir, iwc);

这里先是定义存放索引文件的位置,然后定义分析器(分词器),我这里没有使用昨天提到的一个官方的smartcn那个jar的分词器,自己试了一下,发现不是很好用,居然是搜索失败的。不过中文的话,应该还是IK Analyzer比较好吧。

StandardAnalyzer是 lucene 中内置的“标准分析器”,可以做如下功能:

l  对原有句子按照空格进行了分词

l  所有的大写字母都可以能转换为小写的字母

l  可以去掉一些没有用处的单词,例如”is”,”the”,”are”等单词,也删除了所有的标点

当然这里也可以一些其他的分词器,Lucene中也自带了中文的分词器,是lucene-analyzers-smartcn.Jar中的SmartChineseAnalyzer,但是我用了一下发现对中文的处理并不好。

当然其他的中文分词器还有很流行的IKAnalyzer,这个一定要用FF的版本,意思是for four才是给我们4.x用的。

在下面是定义配置类,这里有个setOpenMode,有下面几个选项:

APPEND:总是追加,可能会导致错误,索引还会重复,导致返回多次结果

CREATE:清空重建(推荐)

CREATE_OR_APPEND【默认】:创建或追加

这里还是建议先用CREATE吧,当然学习的深入了之后使用CREATE_OR_APPEND可能会让索引创建效率更高。

另外,IndexWriter的创建也是相当耗费资源的,所以如有可能,尽量使用单例(注意线程 安全 )。

2、根据数据创建文档

首先说下Field、Document、索引之间的关系,简单一句话:多个Field组成一个Document,多个Document组成一个索引。

在创建索引的过程中比较重要的就是创建不同的Field,看看api就可以知道Field有哪些实现:BinaryDocValuesField, DoubleField, FloatField, IntField, LongField, NumericDocValuesField, SortedDocValuesField, SortedNumericDocValuesField, SortedSetDocValuesField, StoredField, StringField, TextField。

比较常用的有LongField、StoredField、StringField、TextField。具体有哪些构造方法建议大家自己查阅api文档。

每种Field都有具体的介绍,我这里重点介绍一下常用的几个:

LongField:索引但是不分词,适用于全部搜索,一般用于文件创建、修改时间的秒数等。

StoredField:只存不索引

StringField:索引但是不分词,所以适用于全部搜索的内容,比如国家等,要么不对,要么就是全对。另外提一句,这个有个长度限制是32766,大家使用的时候自己斟酌一下,一般不会超过。

TextField:索引并分词,所以这个应该是我们做 全文检索 的时候应该最常用到的一个Field。

Document doc = new Document();
FileInputStream is = new FileInputStream(f);
    Reader reader = new BufferedReader(new InputStreamReader(is));
    // 字符串 StringField LongField TextField
    Field pathField = new StringField("path", f.getAbsolutePath(), Field.Store.YES);
    Field contenField = new TextField("contents", reader);
    // 添加字段
    doc.add(contenField);
    doc.add(pathField);

这样首先声明一个Document,然后声明一系列Field,然后添加字段即可。

这里有个重点就是Field,其实也比较简单。在4.x以前是没有各种各样的Field的,都是通过传参,现在就已经有了不同的实现,可以按需选择了。

StringField即为NOT_ANALYZED的(即不对域的内容进行分割分析),而TextField是ANALYZED的,因此,创建Field对象时,无需再指定分析类型了。

下面是官方描述:

StringField: A field that is indexed but not tokenized

TextField: A field that is indexed and tokenized

下面介绍一些有关Field的相关选项

a. Field.Store.Yes/No

在创建Field的时候,需要传入一个参数,来指定内容是否需要存储到索引中。这些被存储的内容可以在搜索结果中返回,用于展现显示,即使用document.get(“name”)时,是否可以直接返回内容。

一般文件的作者、创建时间、文件名等信息可以存储,但是内容就没必要存储了,一方面是内容太多太大,另一方面也是因为我们的程序可以引导用户直接访问原文件查看即可。

b.加权(后面会细说)

可以对Filed及Document进行加权。注意加权是影响返回结果顺序的一个因素,但也仅仅是一个因素,它和其它因素一起构成了Lucene的排序 算法 。

下面继续介绍一个对富文本(非纯文本)索引的方法。

对于word,excel,pdf等富文本,FileReader读取到的会是 乱码 ,无法有效的索引。这时候可以使用Tika等工具先将其正文内容提取出来,然后再进行索引。

使用Tika进行正文提取的方法见我的github:

https://github.com/irfen/lucene-example/blob/master/src/main/java/me/irfen/lucene/ch03/TikaBasicUtil.java

https://github.com/irfen/lucene-example/blob/master/src/test/java/me/irfen/lucene/ch03/TikaTest.java

更多Tika内容以后如果有时间会详细介绍。这里我使用的是Tika1.5版本,他依赖的包有点多,使用maven进行构建只需要如下两个配置即可:

<dependency>
      <groupId>org.apache.tika</groupId>
      <artifactId>tika-core</artifactId>
      <version>1.5</version>
    </dependency>
    <dependency>
      <groupId>org.apache.tika</groupId>
      <artifactId>tika-parsers</artifactId>
      <version>1.5</version>
    </dependency>

3、向索引库中写入文档内容

这一步很简单,直接就是writer.addDocument(doc);就可以了。

这里简单介绍下对索引的优化,索引过程中,会将索引结果放到多个索引文件中,这样会回收索引的效率,但在搜索时,需要将多个索引文件中的返回结果并进行合并处理,因此效率较低。

在添加文档之后执行writer.forceMerge(2);,索引的优化是将索引结果文件归为一个或者有限的多个,它加大索引过程中的耗时(降低了效率),减少了搜索时的耗时(提高了效率)。

4、关于Directory

目前用的比较多的有两个Directory,一个是FSDirectory,一个是RAMDirectory。

看一眼FSDirectory的源码,会发现下面这段:

public static FSDirectory open(File path, LockFactory lockFactory) throws IOException {
    if (Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) {
      return new MMapDirectory(path, lockFactory);
    } else if (Constants.WINDOWS) {
      return new SimpleFSDirectory(path, lockFactory);
    } else {
      return new NIOFSDirectory(path, lockFactory);
    }
  }

其实FSDirectory是根据不同的操作系统和JRE返回不同的Directory。

而另一个常用的是RAMDirectory,这个是内存索引,只对小索引好用,大量索引会导致频繁GC。

另外介绍一下FileSwitchDirectory,这是一个基于文件目录切换的一个实现。有时候我们想要同时获得两个Directory的优点,这就是FileSwitchDirectory的作用。下面是他的构造方法:

public FileSwitchDirectory(Set primaryExtensions, Directory primaryDir, Directory secondaryDir, boolean doClose) {
  this.primaryExtensions = primaryExtensions;
  this.primaryDir = primaryDir;
  this.secondaryDir = secondaryDir;
  this.doClose = doClose;
  this.lockFactory = primaryDir.getLockFactory();
  }

这里可以看到他要两个Directory,通过第一个参数我们可以指定主索引需要加载的索引文件,其它的将会由从Directory来实现,由此达到快速切换不同的Directory来使用他们各自的优点。

时间: 2024-08-28 08:46:37

Lucene4.9学习笔记——Lucene建立索引的相关文章

Lucene建立索引然后搜索的小Demo

package junitTest; import java.io.IOException; import java.io.StringReader; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.luce

【转】Lucene不同版本中Field的Keyword、UnIndex,导致lucene 建立索引总是报错 急!!

lucene 建立索引 总是报错 急!! http://zhidao.baidu.com/link?url=iaVs9JH4DfN6iwaWImt7VMJENWCWGGaWFGPjqhUw_jz7FsbdrUiAJwptgCNDR8OhWlJ8iUArECkLnpBQGGzTxq 这段话总是报错,编译不过去.红线画在keyword,text下面.while(rs.next()){ Document doc=new Document(); doc.add(Field.Keyword("BH&quo

lucene 建立索引的过程

时间 2014-06-30 17:56:52 ? CSDN博客 原文 http://blog.csdn.net/caohaicheng/article/details/35992149 看lucene主页(http://lucene.apache.org/)上目前lucene已经到4.9.0版本了, 参考学习的书是按照2.1版本讲解的,写的代码例子是用的3.0.2版本的,版本 的不同导致有些方 法的 使用差异,但是大体还是相同的. 源代码用到的jar包(3.0.2版本)下载地址 参考资料: 1.

lucene 建立索引与查询

Lucene 简介 Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能.Lucene 目前是 Apache Jakarta 家族中的一个开源项目.也是目前最为流行的基于 Java 开源全文检索工具包. 目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能.Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行

Lucene建立索引库

问题?Lucene如何建立索引库,lucene所需要的jar包是那些  , lucene如何使用索引库,lucene的核心原理 一.Lucene是什么? 全文检索只是一个概念,而具体实现有很多框架,lucene是其中的一种方式.本文将以lucene3.0进行开发 官兵与Luncne的jar包可以去官网下载:点击打开链接,不过好像Lucene已经更新到6.1了. 二.建立索引库 1.互联网搜索全文搜索引擎结构图: 2.Lucene的结构图: 说明: (1)在数据库中,数据库中的数据文件存储在磁盘上

lucene建立索引的过程

建立索引过程 用户提交数据=>solr建立索引=>调用lucene包建立索引 官方建立索引和查询索引的例子如下: http://lucene.apache.org/core/4_10_3/demo/overview-summary.html#About_the_code http://lucene.apache.org/core/4_10_3/core/overview-summary.html#overview_description 其他参考文章如下: http://dataknocker

MongoDB学习笔记四:索引

索引就是用来加速查询的.创建数据库索引就像确定如何组织书的索引一样.但是你的优势是知道今后做何种查询,以及哪些内容需要快速查找.比如:所有的查询都包括"date"键,那么很可能(至少)需要建立一个关于"date"的索引.如果要查询用户名,则不必索引"user_num"键,因为根本不会对其进行查询.现在要依照某个键进行查找:> db.people.find({"username" : "mark"})当

MySQL学习笔记(六):索引

本文主要介绍MySQL 中关于索引的一些问题,例如:索引的作用:怎么创建索引:设计索引的原则:怎么优化索引等等. 一:索引概述 所有的MySQL列类型都能创建索引,良好设计的所以能够很好地提高查询的性能,但如果索引过多,由于每次更新操作都会对索引进行更新,反而会影响到数据库的整体性能.因而,遵循一定的原则,设计合适的索引是非常重要的. (1):创建索引的语法 CREATE [UNIQUE|FULLTEXT|SPQTIAL] INDEX index_name [USING index_type]

SQL反模式学习笔记13 使用索引

2014-10-14 10:29:53 目标:优化性能 改善性能最好的技术就是在数据库中合理地使用索引.  索引也是数据结构,它能使数据库将指定列中的某个值快速定位在相应的行. 反模式:无规划的使用索引 1.不使用索引或索引不足 2.使用了太多的索引或一些无效的索引 (1)大多数数据库会自动地位主键建立索引,因此额外再定义一个索引就是冗余. 这个额外的索引并无任何好处,它只会成为额外的开销. (2)字符串索引很大,而且也不太可能对它进行全匹配查找. (3)使用组合索引是一个很好的选择,但是大部分