引言
目前最新的Lucene的版本是2.4.0,但关于索引文件格式(Index File Format)的说明并未完全及时更新,所以后文是基于版本2.1.0展开的解析。解析内容并未涉及全面,更多详细准确的说明还请参见[1]。
在看下文之前,若熟悉Lucene的索引的基本概念和过程就会对后文的理解有很大帮助。
创建一个简单的索引
这里有一段代码,它将创建一个简单的索引段(Segment),这个段只有一个文档(Document),文档中有两个域(Field):name和description。两个域均进行索引(Index)并保存(Store),区别在于后者需要分词(Tokenized),代码如下:
public class App {
public static void main(String[] args) {
Document doc = new Document();
Field[] fields = createFields();
for (int i = 0; i < fields.length; i++) {
doc.add(fields[i]);
}
createIndex(doc);
}
private static void createIndex(Document doc) {
try {
boolean create = true;
IndexWriter writer = new IndexWriter("index",
new StandardAnalyzer(), create);
writer.setUseCompoundFile(false);
writer.addDocument(doc);
writer.optimize();
writer.close();
} catch (IOException e) {
// 异常处理
}
}
private static Field[] createFields() {
Field name = new Field("name", "allen", Field.Store.YES,
Field.Index.UN_TOKENIZED);
Field desc = new Field("description", "i'm a new coder for lucene.",
Field.Store.YES, Field.Index.TOKENIZED);
return new Field[] { name, desc };
}
}
注意上面代码中,有:
writer.setUseCompoundFile(false);
这里避免了1.4本版之后就默认采用合成模式,而是采用传统模式,这是为了方便索引文件格式的分析,二者原理是一致的。
传统模式下产生的索引文件将会是:
2008-12-11 17:12 20 segments.gen
2008-12-11 17:12 41 segments_6
2008-12-11 17:12 39 _2.fdt
2008-12-11 17:12 8 _2.fdx
2008-12-11 17:12 20 _2.fnm
2008-12-11 17:12 5 _2.frq
2008-12-11 17:12 6 _2.nrm
2008-12-11 17:12 5 _2.prx
2008-12-11 17:12 31 _2.tii
2008-12-11 17:12 72 _2.tis
注意,这里出现的文件名前缀若不是“_2”也没有关系。
关于域
关于域会涉及上面三个文件,第一个是.fnm,它的作用是保存所有的域名的信息,其文件的十六进制内容如下:
.fnm
02 0B 64 65 73 63 72 69 70 74 69 6F 6E 01 04 6E 61 6D 65 01
- 02 表示所有域的个数为2;
- 0B 表示第一个域名的字符串长度为11;
- 64 65 73 63 72 69 70 74 69 6F 6E 是“description”的UTF-8的编码;
- 01 表示第一个域是创建了索引的,这里应转换成二进制为按位的0/1值来判断索引配置信息(详见[1])。
剩余的部分是另一域“name”的数据。由此可见,fnm文件的格式为:<域个数>[<域名长度><域名字符串><域的索引配置> ...]。
fnm中域名是根据字母表进行排序了的,这是很重要的,后文的项字典(Term Dictionary)中项(Term)的顺序就是按照它对应的域顺序来排的。
fnm的内容可以转换下面比较容易理解的表格:
Field Name |
Indexed? |
Vectored? |
Positions Stored? |
Offsets Stored? |
Norms Omitted? |
Payloads Stored? |
description |
√ |
- |
- |
- |
- |
- |
name |
√ |
- |
- |
- |
- |
- |
第二文件是.fdx,它的作用是记录每个文档所有存储的域数据(Field Data)在.fdt文件中的开始位置,其文件的十六进制内容如下:
.fdx
00 00 00 00 00 00 00 00
8个字节的0似乎没有给我们任何信息,这是由于创建索引的代码中只添加了一个文档,显然这里已经表示了文档的开始位置为0。为了让解析更有说服力,此时将上述代码做如下调整:
boolean create = false;// 之前是true,这里设为false代表IndexWriter将在已存在的文件中添加内容
private static Field[] createFields() {
Field name = new Field("name", "rocky", Field.Store.YES,
Field.Index.UN_TOKENIZED);
Field desc = new Field("description", "a expert of lucene.",
Field.Store.YES, Field.Index.TOKENIZED);
return new Field[] { name, desc };
}// 修改数据,以添加一个新的文档
再次运行代码,便会在索引中添加一个新的文档。此时,再看.fdx文件内容(文件名前缀发生了变化):
.fdx
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27
显而易见,内容由两个8个字节的十六进制数组成,它们分别代表两个文档的域数据在.fdt中的开始位置,第一文档是0,第二个文档是27*8。那么,fdx的文件格式很简单:[<文档域值的开始位置>...]。
来看看.fdt吧,里面记录着定义要存储的域数据:
.fdt
02 01 00 05 61 6C 6C 65 6E 00 01 1B 69 27 6D 20 ....allen...i'm
61 20 6E 65 77 20 63 6F 64 65 72 20 66 6F 72 20 a new coder for
6C 75 63 65 6E 65 2E 02 01 00 05 72 6F 63 6B 79 lucene.....rocky
00 01 13 61 20 65 78 70 65 72 74 20 6F 66 20 6C ...a expert of l
75 63 65 6E 65 2E ucene.
- 02 表示记录了域数据的文档个数为2;
- 01 表示域的序号为1,也就是后面的数据是name域的值(见fnm中name是排在第二位的);
- 00 表示后面数据没有经过分词,是字符串,且没有进行压缩处理,这里应转换成二进制为按位的0/1值来判断数据的状态的(详见[1]),数据也有可能是BinaryValue;
- 05 表示字符串的长度;
- 61 6C 6C 65 6E 表述字符串“allen”。
余下的数据依此类推。这样,fdt的格式也很清晰了:<文档个数>[<域序号><域状态><域数据长度><域数据>...]
未完待续,下一部分聊“项”...
参考资料
[1] Apache Lucene - Index File Formats
[2] Lucene:基于Java的全文检索引擎简介
[3] 深入 Lucene 索引机制
[4] " Lucene In Action" by Erik Hatcher, Otis Gospodnetić; Manning Publications; December 2004; ISBN 1932394281
分享到:
相关推荐
iTextPDFExtractor.java ------ ...--PDFBox创建PDF文件的Lucene索引 PDFBoxPathIndex.java ------- --PDFBox创建指定目录PDF文档索引 POIOfficeExtractor.java ----- -- POI处理Excel和Word文档代码
《Lucene索引文件格式详解》 Lucene,作为一款强大的全文搜索引擎库,其索引文件格式是实现高效搜索的关键。本文将深入解析Lucene 1.3版本的索引文件结构,帮助读者理解其内部运作机制。 首先,我们要理解Lucene...
在Lucene的索引结构中,每个段包含_N.fdx和_N.fdt文件,分别存储Field Data的地址指针和文档内容。此外,每个词项还有对应的倒排索引表,记录了该词在各个文档中的出现位置。例如,_N.vidx和_N.vtf文件分别存储词汇...
本篇内容将详细解析Lucene的索引结构,帮助你更好地理解和运用这个强大的工具。 首先,我们要明白索引的基本构成。在Lucene中,索引是由一系列文档(document)组成的,每个文档包含多个域(field),每个域又由多...
- **多线程索引**: 为了提高效率,Lucene支持多线程并行索引多个文件。 - **内存缓存**: 常见的查询可以被缓存,提升查询速度。 - **分布式搜索**: 通过Solr或Elasticsearch等工具,Lucene可以实现分布式搜索,...
- **基本概念**:介绍Lucene索引文件的基本术语和概念。 - **基本类型**:定义了索引文件中使用的数据类型。 - **基本规则**:阐述了文件格式设计的基本原则。 - **具体格式**: - **正向信息**:包括段元数据、...
Lucene作为一个强大的文本搜索库,其核心功能包括建立索引和执行搜索。以下是关于Lucene2.9开发的一些关键知识点: 1. **搭建开发环境**: 开发者需要在Java项目的classpath中添加`lucene-core-2.9.1.jar`,这是...
3. Lucene的索引文件逻辑结构 1) 索引(Index)由若干块(片段)(Segment)组成 ★2) 块由若干文档(Document)组成: 一个文件映射成一个文档。数据库表中的一条记录映射成一个文档。 ★3) 文档由若干域(Field)组成:...
通过xpdf,可以从Pdf文件中准确地抽取文本内容,使其能够被Lucene索引和检索。具体步骤如下: 1. **下载并安装xpdf**: 首先,从官方网站http://www.foolabs.com/xpdf/ 下载xpdf工具包,并按照指南完成安装。 2. **...
Lucene的索引文件格式包括正向信息和反向信息,其中正向信息包含段的元数据、域的元数据、域的数据信息、词向量的数据信息等,而反向信息包括词典信息、文档号及词频信息、词位置信息等。Lucene的索引过程体系结构...
1. **跨平台性**:Lucene定义了一套以8位字节为基础的索引文件格式,这意味着索引文件可以在不同的应用平台之间共享,提高了系统的互操作性和可移植性。 2. **高效的索引机制**:Lucene在传统全文检索引擎的倒排索引...
二、Lucene索引流程 1. 文档分词:Lucene使用Analyzer对输入的文档进行分词,生成Token流。 2. 字符串到Term:将分词结果转化为Term对象,每个Term代表一个唯一的词汇项。 3. 建立Term Frequency(TF):记录每个...
Lucene索引文件格式分析 ##### 3.1 源码实现分析 Lucene的源码实现了多种数据结构和算法,以优化索引的存储和查询效率。深入理解这些实现机制,有助于开发者更好地利用Lucene的性能优势,或在其基础上进行二次开发...
4. document模块:封装了索引文件的基本结构,如Document和Field类。 5. search模块:处理索引的搜索,如IndexSearcher和各种Query类。 6. queryParser模块:解析用户的查询语句,生成相应的Query对象。 7. util模块...
在实践中,Lucene可以处理多种格式的文件,如Word、Excel、PPT和PDF,这些文件通过特定的解析器(如Apache POI和PDFBox)将内容提取出来,然后进行索引。通过封装接口,开发者可以轻松地将这些功能整合到自己的应用...
#### 四、Lucene索引过程分析 索引过程是全文检索系统中最复杂的环节之一,涉及到大量的内部处理和优化策略。主要包括以下几个步骤: - **创建IndexWriter对象**:用于创建和管理索引的工具类。 - **创建文档...
- `Directory`: 用于存储索引数据的抽象接口,例如FSDirectory(文件系统目录)和RAMDirectory(内存目录)。 - `IndexWriter`: 负责创建、修改和删除索引的主要类,可以添加、删除和更新文档。 - `Document`: 代表...
//创建一个IndexWriter(存放索引文件的目录,分析器,Field的最大长度) iwriter = new IndexWriter(directory, analyzer,true, IndexWriter.MaxFieldLength.UNLIMITED); //iwriter.setUseCompoundFile(true);//...