当前位置: 首页 > lucene, 搜索 > 正文

分析lucene4建立索引计算norm

1 星2 星3 星4 星5 星 (1 次投票, 评分: 5.00, 总分: 5)
Loading ... Loading ...
baidu_share
文章目录

norm(t,d)介绍

norm(t,d)压缩几个索引期间的加权和长度因子:

1.Document boost – 文档加权,在索引之前使用 doc.setBoost()
2.Field boost – 字段加权,也在索引之前调用 field.setBoost()
3.lengthNorm(field) – 由字段内的 Token 的个数来计算此值,字段越短,评分越高,在做索引的时候由 Similarity.lengthNorm 计算。

以上所有因子相乘得出 norm 值,如果文档中有相同的字段,它们的加权也会相乘:
norm

索引的时候,把 norm 值压缩(encode)成一个 byte 保存在索引中。搜索的时候再把索引中 norm 值解压(decode)成一个 float 值,这个 encode/decode 由 Similarity 提供。官方说:这个过程由于精度问题,以至不是可逆的,如:decode(encode(0.89)) = 0.75。

分析computeNorm()

以lucene4.5为例,来说明lucene4建立索引时,norm值得计算。核心代码如下:

Directory dir=new RAMDirectory();
        IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_45,new StandardAnalyzer(Version.LUCENE_45));
        IndexWriter writer = new IndexWriter(dir,config); 
        Document doc1 = new Document();  
        doc1.add(new TextField("bookname","bc bc", Store.YES)); 
        writer.addDocument(doc1);  
        writer.close();

当建立索引的时候,会调用DefaultSimilarity的computeNorm()方法(继承TFIDFSimilarity得到该方法)来计算norm值。

1.TFIDFSimilarity的computeNorm()方法

  public final long computeNorm(FieldInvertState state) {
    //计算lengNorm值
    float normValue = lengthNorm(state);
    //把 norm 值压缩(encode)成一个 byte 
    return encodeNormValue(normValue);
  }

2.DefaultSimilarity的lengthNorm()方法

  public float lengthNorm(FieldInvertState state) {
    final int numTerms;// 分词出来的term数量。例如:"ab bc",numTerms就为2
    if (discountOverlaps)//是否忽略指定的term数量  
      numTerms = state.getLength() - state.getNumOverlap();
    else
      numTerms = state.getLength();
   //state.getBoost()为该field的boost。文档没有boost。
   return state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms)));
  }

3.DefaultSimilarity的encodeNormValue()方法

  public final long encodeNormValue(float f) {
    return SmallFloat.floatToByte315(f);
  }

4.SmallFloat的floatToByte315方法

/** floatToByte(b, mantissaBits=3, zeroExponent=15)
   * <br>smallest non-zero value = 5.820766E-10
   * <br>largest value = 7.5161928E9
   * <br>epsilon = 0.125
   */
  public static byte floatToByte315(float f) {
    int bits = Float.floatToRawIntBits(f);
    int smallfloat = bits >> (24-3);
    if (smallfloat <= ((63-15)<<3)) {
      return (bits<=0) ? (byte)0 : (byte)1;
    }
    if (smallfloat >= ((63-15)<<3) + 0x100) {
      return -1;
    }
    return (byte)(smallfloat - ((63-15)<<3));
 }

lucene中采用1个byte来存储lengthNorm的值,默认是采用3个bit来区分这个值,最小单位为0.125.最多存储了256个不同的boost。当boost设置成20或者23时候,是没有区别的。所以会造成精度上的损失.

一个文档中有多个field,会多次调用computeNorm()方法。一个field对应一个norm值。

查看lucene索引,可以使用luke,但是该版本只支持到lucene4.0,高一点版本lucene查看不了。

本文固定链接: http://www.chepoo.com/analysis-lucene4-indexing-calculated-norm.html | IT技术精华网

【上一篇】
【下一篇】

分析lucene4建立索引计算norm:等您坐沙发呢!

发表评论