Jakarta Lucene是用Java写成的同时有很多团体正在默默的用其他的程序语言来改写它如果这些新的版本想和Jakarta Lucene兼容就需要一个与具体语言无关的Lucene索引文件格式本文正是试图提供一个完整的与语言无关的Jakarta Lucene 索引文件格式的规格定义 随着Lucene不断发展本文也应该更新不同语言写成的Lucene实现版本应当尽力遵守文件格式也必须产生本文的新版本 本文同时提供兼容性批注描述文件格式上与前一版本不同的地方 定义 Lucene中最基础的概念是索引(index)文档(document.域(field)和项(term) 索引包含了一个文档的序列 · 文档是一些域的序列 · 域是一些项的序列 · 项就是一个字串 存在于不同域中的同一个字串被认为是不同的项因此项实际是用一对字串表示的第一个字串是域名第二个是域中的字串 倒排索引 为了使得基于项的搜索更有效率索引中项是静态存储的Lucene的索引属于索引方式中的倒排索引因为对于一个项这种索引可以列出包含它的文档这刚好是文档与项自然联系的倒置 域的类型 Lucene中域的文本可能以逐字的非倒排的方式存储在索引中而倒排过的域称为被索引过了域也可能同时被存储和被索引 域的文本可能被分解许多项目而被索引或者就被用作一个项目而被索引大多数的域是被分解过的但是有些时候某些标识符域被当做一个项目索引是很有用的 段(Segment) Lucene索引可能由多个子索引组成这些子索引成为段每一段都是完整独立的索引能被搜索索引是这样作成的 为新加入的文档创建新段 合并已经存在的段 搜索时需要涉及到多个段和/或者多个索引每一个索引又可能由一些段组成 文档号(document.nbspNumber) 内部的来说Lucene用一个整形(interger)的文档号来指示文档第一个被加入到索引中的文档就是号顺序加入的文档将得到一个由前一个号码递增而来的号码 注意文档号是可能改变的所以在Lucene外部存储这些号码时必须小心特别的号码的改变的情况如下 · 只有段内的号码是相同的不同段之间不同因而在一个比段广泛的上下文环境中使用这些号码时就必须改变它们标准的技术是根据每一段号码多少为每一段分配一个段号将段内文档号转换到段外时加上段号将某段外的文档号转换到段内时根据每段中可能的转换后号码范围来判断文档属于那一段并减调这一段的段号例如有两个含个文档的段合并那么第一段的段号就是第二段段号第二段中的第三个文档在段外的号码就是 · 文档删除后连续的号码就出现了间断这可以通过合并索引来解决段合并时删除的文档相应也删掉了新合并而成的段并没有号码间断 绪论 索引段维护着以下的信息 · 域集合包含了索引中用到的所有的域 · 域值存储表每一个文档都含有一个属性-值对的列表属性即为域名这个列表用来存储文档的一些附加信息如标题url或者访问数据库的一个ID在搜索时存储域的集合可以被返回这个表以文档号标识 · 项字典这个字典含有所有文档的所有域中使用过的的项同时含有使用过它的文档的文档号以及指向使用频数信息和位置信息的指针 · 项频数信息对于项字典中的每个项这些信息包含含有这个项的文档的总数以及每个文档中使用的次数 · 项位置信息对于项字典中的每个项都存有在每个文档中出现的各个位置 · Normalization factors For each field in each document. a value is stored that is multiplied into the score for hits on that field 标准化因子对于文档中的每一个域存有一个值用来以后乘以这个这个域的命中数(hits) · 被删除的文档信息这是一个可选文件用来表明那些文档已经删除了 接下来的各部分部分详细描述这些信息 文件的命名(File Naming) 同属于一个段的文件拥有相同的文件名不同的扩展名扩展名由以下讨论的各种文件格式确定 一般来说一个索引存放一个目录其所有段都存放在这个目录里尽管我们不要求您这样做 基本数据类型(Primitive Types) Byte 最基本的数据类型就是字节(byte位)文件就是按字节顺序访问的其它的一些数据类型也定义为字节的序列文件的格式具有字节意义上的独立性 UInt 位无符号整数由四个字节组成高位优先 UInt > <Byte> Uint 位无符号整数由八字节组成高位优先 UInt > <Byte> VInt 可变长的正整数类型每字节的最高位表明还剩多少字节每字节的低七位表明整数的值因此单字节的值从到两字节值从到等等 VInt 编码示例 value First byte Second byte Third byte 这种编码提供了一种在高效率解码时压缩数据的方法 Chars Lucene输出UNICODE字符序列使用标准UTF编码 String Lucene输出由VINT和字符串组成的字串VINT表示字串长字符串紧接其后 String > VInt Chars 索引包含的文件(PerIndex Files) 这部分介绍每个索引包含的文件 Segments文件 索引中活动的段存储在Segments文件中每个索引只能含有一个这样的文件名为segments这个文件依次列出每个段的名字和每个段的大小 Segments > SegCount <SegName SegSize>SegCount SegCount SegSize > UInt SegName > String SegName表示该segment的名字同时作为索引其他文件的前缀 SegSize是段索引中含有的文档数 Lock文件 有一些文件用来表示另一个进程在使用索引 · 如果存在commitlock文件表示有进程在写segments文件和删除无用的段索引文件或者表示有进程在读segments文件和打开某些段的文件在一个进程在读取segments文件段信息后还没来得及打开所有该段的文件前这个Lock文件可以防止另一个进程删除这些文件 · 如果存在indexlock文件表示有进程在向索引中加入文档或者是从索引中删除文档这个文件防止很多文件同时修改一个索引 Deleteable文件 名为deletetable的文件包含了索引不再使用的文件的名字这些文件可能并没有被实际的删除这种情况只存在与Win平台下因为Win下文件仍打开时并不能删除 Deleteable > DelableCount <DelableName>DelableCount DelableCount > UInt DelableName > String 段包含的文件(PerSegment Files) 剩下的文件是每段中包含的文件因此由后缀来区分 域(Field) 域集合信息(Field Info) 所有域名都存储在这个文件的域集合信息中这个文件以后缀fnm结尾 FieldInfos (fnm) > FieldsCount <FieldName FieldBits>FieldsCount FieldsCount > VInt FieldName > String FieldBits > Byte 目前情况下FieldBits只有使用低位对于已索引的域值为对未索引的域值为 文件中的域根据它们的次序编号因此域是文件中的第一个域域是接下来的等等这个和文档号的编号方式相同 域值存储表(Stored Fields) 域值存储表使用两个文件表示 域索引(fdx文件) 如下对于每个文档这个文件包含指向域值的指针 FieldIndex (fdx) > <FieldvaluesPosition>SegSize FieldvaluesPosition > Uint FieldvaluesPosition指示的是某一文档的某域的域值在域值文件中的位置因为域值文件含有定长的数据信息因而很容易随机访问在域值文件中文档n的域值信息就存在n* |