Lucene fieldNorm相似度计算和查询时间值之间的差异

Lucene fieldNorm相似度计算和查询时间值之间的差异,lucene,indexing,metrics,Lucene,Indexing,Metrics,我试图理解fieldNorm是如何计算(在索引时)并在查询时使用(显然是重新计算)的 在所有的例子中,我都在使用StandardAnalyzer,没有停止词 在索引内容时使用DefaultSimilarity的computeNorm方法,我注意到它会返回两个特定文档: 文档A为0.5(其字段中有4个标记) 文档B的0.70710677(其字段中有2个令牌) 它通过使用以下公式来实现: state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms)

我试图理解
fieldNorm
是如何计算(在索引时)并在查询时使用(显然是重新计算)的

在所有的例子中,我都在使用StandardAnalyzer,没有停止词

在索引内容时使用
DefaultSimilarity
computeNorm
方法,我注意到它会返回两个特定文档:

  • 文档A为0.5(其字段中有4个标记)
  • 文档B的0.70710677(其字段中有2个令牌)
它通过使用以下公式来实现:

state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms)));
其中boost总是1

之后,当我查询这些文档时,我会在查询解释中看到

  • 0.5=fieldNorm(field=titre,doc=0)
    用于文档A
  • 0.625=fieldNorm(field=titre,doc=1)
    用于文档B
这已经很奇怪了(对我来说,我确信是我错过了一些东西)。为什么我得不到与索引时计算的相同的字段范数值?这就是“查询规范化”的作用吗?如果是,它是如何工作的

但是,这或多或少是正常的,因为两个查询时间字段规范给出的顺序与在索引时间计算的顺序相同(在这两种情况下,值较短的字段具有较高的字段规范)

然后我创建了自己的相似性类,在其中我实现了computeNorms方法,如下所示:

public float computeNorm(String pField, FieldInvertState state) {
    norm = (float) (state.getBoost() + (1.0d / Math.sqrt(state.getLength())));
    return norm;
}
在索引时,我现在得到:

  • 1.5对于文档A(其字段中有4个标记)
  • 1.7071068用于文档B(其字段中有2个令牌)
但是现在,当我查询这些文档时,我可以看到它们都具有与explain函数报告的相同的字段规范:

  • 1.5=fieldNorm(field=titre,doc=0)
    用于文档A
  • 1.5=fieldNorm(field=titre,doc=1)
    用于文档B
对我来说,这真的很奇怪,如果我在索引时使用一个明显很好的相似性来计算fieldNorm,它会给我与令牌数量成比例的适当值,那么在查询时,所有这些都会丢失,并且查询sais两个文档都具有相同的字段norm

因此,我的问题是:

  • 为什么相似性的computeNorm方法报告的索引时间字段规范与查询解释报告的索引时间字段规范不同
  • 为什么,对于在索引时获得的两个不同的fieldNorm值(通过相似度计算),我在查询时得到相同的fieldNorm值
==更新

好的,我发现一些东西澄清了我的一些问题,但不是全部:

但是,在存储之前,生成的规范值被编码为单个字节。在搜索时,从索引目录中读取norm字节值,并将其解码回浮点norm值。这种编码/解码在减少索引大小的同时,也带来了精度损失的代价——不能保证解码(encode(x))=x。例如,解码(编码(0.89))=0.75

精度损失有多大?我们是否应该在不同的值之间设置一个最小间隙,以便即使在精度损失重新计算后,它们仍保持不同?

的文档描述了编码步骤(即精度损失的步骤),特别是值的最终表示:

编码使用三位尾数、五位指数和15处的零指数点,因此表示从7x10^9到2x10^-9的值,精度约为一个有效十进制数字。也表示零。负数四舍五入为零。太大而无法表示的值将向下舍入到最大的可表示值。太小而无法表示的正值将向上舍入到最小的可表示正值

最相关的一点是尾数只有3位,这意味着精度大约是一个有效的十进制数字

关于基本原理的一个重要说明是,在你的引文结束后的几句话中,Lucene文档说:

支持范数值有损压缩的基本原理是,考虑到用户很难(且不准确)通过查询表达其真实信息需求,只有大的差异才重要

的文档描述了编码步骤(即精度损失的步骤),特别是值的最终表示形式:

编码使用三位尾数、五位指数和15处的零指数点,因此表示从7x10^9到2x10^-9的值,精度约为一个有效十进制数字。也表示零。负数四舍五入为零。太大而无法表示的值将向下舍入到最大的可表示值。太小而无法表示的正值将向上舍入到最小的可表示正值

最相关的一点是尾数只有3位,这意味着精度大约是一个有效的十进制数字

关于基本原理的一个重要说明是,在你的引文结束后的几句话中,Lucene文档说:

支持范数值有损压缩的基本原理是,考虑到用户很难(且不准确)通过查询表达其真实信息需求,只有大的差异才重要