4.1.2. 域(Field)的元数据信息(.fnm)

一个段(Segment)包含多个域,每个域都有一些元数据信息,保存在.fnm文件中,.fnm文件的格式如下:

  • FNMVersion

    • 是fnm文件的版本号,对于Lucene 2.9为-2
  • FieldsCount
    • 域的数目
  • 一个数组的域(Fields)
    • FieldName:域名,如"title","modified","content"等。
    • FieldBits:一系列标志位,表明对此域的索引方式
      • 最低位:1表示此域被索引,0则不被索引。所谓被索引,也即放到倒排表中去。

        • 仅仅被索引的域才能够被搜到。
        • Field.Index.NO则表示不被索引。
        • Field.Index.ANALYZED则表示不但被索引,而且被分词,比如索引"hello world"后,无论是搜"hello",还是搜"world"都能够被搜到。
        • Field.Index.NOT_ANALYZED表示虽然被索引,但是不分词,比如索引"hello world"后,仅当搜"hello world"时,能够搜到,搜"hello"和搜"world"都搜不到。
        • 一个域除了能够被索引,还能够被存储,仅仅被存储的域是搜索不到的,但是能通过文档号查到,多用于不想被搜索到,但是在通过其它域能够搜索到的情况下,能够随着文档号返回给用户的域。
        • Field.Store.Yes则表示存储此域,Field.Store.NO则表示不存储此域。
      • 倒数第二位:1表示保存词向量,0为不保存词向量。
        • Field.TermVector.YES表示保存词向量。
        • Field.TermVector.NO表示不保存词向量。
      • 倒数第三位:1表示在词向量中保存位置信息。
        • Field.TermVector.WITH_POSITIONS
      • 倒数第四位:1表示在词向量中保存偏移量信息。
        • Field.TermVector.WITH_OFFSETS
      • 倒数第五位:1表示不保存标准化因子
        • Field.Index.ANALYZED_NO_NORMS
        • Field.Index.NOT_ANALYZED_NO_NORMS
      • 倒数第六位:是否保存payload

要了解域的元数据信息,还要了解以下几点:

  • 位置(Position)和偏移量(Offset)的区别

    • 位置是基于词Term的,偏移量是基于字母或汉字的。

  • 索引域(Indexed)和存储域(Stored)的区别

    • 一个域为什么会被存储(store)而不被索引(Index)呢?在一个文档中的所有信息中,有这样一部分信息,可能不想被索引从而可以搜索到,但是当这个文档由于其他的信息被搜索到时,可以同其他信息一同返回。
    • 举个例子,读研究生时,您好不容易写了一篇论文交给您的导师,您的导师却要他所第一作者而您做第二作者,然而您导师不想别人在论文系统中搜索您的名字时找到这篇论文,于是在论文系统中,把第二作者这个Field的Indexed设为false,这样别人搜索您的名字,永远不知道您写过这篇论文,只有在别人搜索您导师的名字从而找到您的文章时,在一个角落表述着第二作者是您。
  • payload的使用
    • 我们知道,索引是以倒排表形式存储的,对于每一个词,都保存了包含这个词的一个链表,当然为了加快查询速度,此链表多用跳跃表进行存储。
    • Payload信息就是存储在倒排表中的,同文档号一起存放,多用于存储与每篇文档相关的一些信息。当然这部分信息也可以存储域里(stored Field),两者从功能上基本是一样的,然而当要存储的信息很多的时候,存放在倒排表里,利用跳跃表,有利于大大提高搜索速度。
    • Payload的存储方式如下图:

  • Payload主要有以下几种用法:

    • 存储每个文档都有的信息:比如有的时候,我们想给每个文档赋一个我们自己的文档号,而不是用Lucene自己的文档号。于是我们可以声明一个特殊的域(Field)"_ID"和特殊的词(Term)"_ID",使得每篇文档都包含词"_ID",于是在词"_ID"的倒排表里面对于每篇文档又有一项,每一项都有一个payload,于是我们可以在payload里面保存我们自己的文档号。每当我们得到一个Lucene的文档号的时候,就能从跳跃表中查找到我们自己的文档号。
//声明一个特殊的域和特殊的词

public static final String ID_PAYLOAD_FIELD = "_ID";

public static final String ID_PAYLOAD_TERM = "_ID";

public static final Term ID_TERM = new Term(ID_PAYLOAD_TERM, ID_PAYLOAD_FIELD);

//声明一个特殊的TokenStream,它只生成一个词(Term),就是那个特殊的词,在特殊的域里面。

static class SinglePayloadTokenStream extends TokenStream { 
    private Token token; 
    private boolean returnToken = false;

SinglePayloadTokenStream(String idPayloadTerm) { 
        char[] term = idPayloadTerm.toCharArray(); 
        token = new Token(term, 0, term.length, 0, term.length); 
    }

void setPayloadValue(byte[] value) { 
        token.setPayload(new Payload(value)); 
        returnToken = true; 
    }

public Token next() throws IOException { 
        if (returnToken) { 
            returnToken = false; 
            return token; 
        } else { 
            return null; 
        } 
    } 
}

//对于每一篇文档,都让它包含这个特殊的词,在特殊的域里面

SinglePayloadTokenStream singlePayloadTokenStream = new SinglePayloadTokenStream(ID_PAYLOAD_TERM); 
singlePayloadTokenStream.setPayloadValue(long2bytes(id)); 
doc.add(new Field(ID_PAYLOAD_FIELD, singlePayloadTokenStream));

//每当得到一个Lucene的文档号时,通过以下的方式得到payload里面的文档号

long id = 0; 
TermPositions tp = reader.termPositions(ID_PAYLOAD_TERM); 
boolean ret = tp.skipTo(docID); 
tp.nextPosition(); 
int payloadlength = tp.getPayloadLength(); 
byte[] payloadBuffer = new byte[payloadlength]; 
tp.getPayload(payloadBuffer, 0); 
id = bytes2long(payloadBuffer); 
tp.close();

    • 影响词的评分

      • 在Similarity抽象类中有函数public float scorePayload(byte [] payload, int offset, int length)  可以根据payload的值影响评分。
  • 读取域元数据信息的代码如下:

FieldInfos.read(IndexInput, String)

  • int firstInt = input.readVInt();
  • size = input.readVInt();
  • for (int i = 0; i < size; i++)
    • String name = input.readString();
    • byte bits = input.readByte();
    • boolean isIndexed = (bits & IS_INDEXED) != 0;
    • boolean storeTermVector = (bits & STORE_TERMVECTOR) != 0;
    • boolean storePositionsWithTermVector = (bits & STORE_POSITIONS_WITH_TERMVECTOR) != 0;
    • boolean storeOffsetWithTermVector = (bits & STORE_OFFSET_WITH_TERMVECTOR) != 0;
    • boolean omitNorms = (bits & OMIT_NORMS) != 0;
    • boolean storePayloads = (bits & STORE_PAYLOADS) != 0;
    • boolean omitTermFreqAndPositions = (bits & OMIT_TERM_FREQ_AND_POSITIONS) != 0;

转载于:https://www.cnblogs.com/bonelee/p/6394248.html

lucene正向索引(续)——域(Field)的元数据信息在.fnm里,在倒排表里,利用跳跃表,有利于大大提高搜索速度。...相关推荐

  1. lucene正向索引(续)——每次commit会形成一个新的段,段_1的域和词向量信息可能存在_0.fdt和_0.fdx”中...

    DocStoreOffset DocStoreSegment DocStoreIsCompoundFile 对于域(Stored Field)和词向量(Term Vector)的存储可以有不同的方式, ...

  2. lucene正向索引——正向信息,Index – Segments (segments.gen, segments_N) – Field(fnm, fdx, fdt) – Term (tvx, ...

    转自:http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623599.html 上面曾经交代过,Lucene保存了从Index到Segm ...

  3. Lucene学习总结之三:Lucene的索引文件格式(1)

    Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙. 当我们真正进入到Lucene源代码之中的时候,我们会发现: Lucene的索引过程, ...

  4. Lucene学习总结之三:Lucene的索引文件格式(2)

    2019独角兽企业重金招聘Python工程师标准>>> 四.具体格式 上面曾经交代过,Lucene保存了从Index到Segment到Document到Field一直到Term的正向 ...

  5. Lucene构建索引的原理及源代码分析

    文章目录 1. Lucene是什么 2. 全文检索是什么 3. 术语 4. 创建索引过程 4.1 Lucene创建索引示例代码 4.2 分词的过程 4.2.1 原理 4.2.2 源代码 4.3 建索引 ...

  6. ElasticSearch——倒排索引和正向索引

    ElasticSearch--倒排索引和正向索引 1.正向索引 正向索引 (forward index) 以文档的ID为关键字,表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出 ...

  7. 倒排文件索引(Inverted File Index)的建立

    建立索引 目前主流的索引技术有三种:倒排文件.后缀数组和签名.后缀数组的方法虽然快,但是其维护困难,代价相当高,不适合做引擎的索引.签名是一种很好的索引方式,但倒排文件的速度和性能已经超过了签名.倒排 ...

  8. Lucene随笔-Lucene的索引文件格式

    Lucene 6.5.1 建立一个Lucene示例 数据写入 public class Writer {private static final String PATH = ""; ...

  9. Lucene学习之四:Lucene的索引文件格式(3)

    本文转载自:http://www.cnblogs.com/forfuture1978/archive/2010/02/02/1661436.html ,略有删改和备注. 四.具体格式 4.2. 反向信 ...

最新文章

  1. (转)CentOS 5.5 64bit 编译安装Adobe FlashMediaServer 3.5
  2. iec61850采样协议(9-1、9-2)解析(二)
  3. ambari 维护模式及reset API 操作
  4. .NET Framework总结二
  5. 第 4 章  超链接和路径
  6. IDEA开发中,类的头位置生成作者时间信息
  7. Java 即将迎来转折点?
  8. 【LeetCode笔记】338. 比特位计数(Java、位运算、动态规划)
  9. 今日早上出来还是阴天
  10. 塘沽十三中2021年高考成绩查询,2020天津高考成绩查询
  11. Emacs:报错:File error: Cannot open load file,cl-lib解决
  12. Windows Embedded Compact 7中的进程和线程(上)
  13. 电商购物网站 - 需求与设计
  14. 系统架构升级建议书(1)
  15. 从离职之日起,一年内仲裁
  16. springboot网上订餐管理系统设计与实现.rar(项目源码)
  17. 新概念下兴起域名商机 云域名是神马浮云
  18. Ubuntu 20.04 server乌班图服务器部署django,uwsgi,mysql,nginx细节
  19. 给windows7系统盘瘦身
  20. python彩虹图_python绘制彩虹图教程

热门文章

  1. jquery实现上下左右键盘监听_python 使用pygame工具包实现贪吃蛇游戏(多彩版)
  2. python操作js中的输入_Python调用JavaScript代码的方法
  3. 分时线的9代表什么_为什么要打板?资深股民分享打板技巧和思路,句句精辟!...
  4. php yof框架特点_腾讯正式开源高性能超轻量级 PHP 框架 Biny
  5. linux php curl 安装包下载,linux中php如何安装CURL扩展方法
  6. mysql sum计算效率很慢_MySQL--RDS下的分区表实践(文末附MySQL视频教程与面试题)...
  7. Nginx面试!java语言程序设计第四版,你还看不懂吗?
  8. 【PAT (Advanced Level) Practice】1008 Elevator (20 分)
  9. 【微信小程序企业级开发教程】事件相关详解
  10. log4j中调试与错误日志分开_idea中log4j日志插件报错