据我了解,给定文档的字段长度是在给定文档的字段中索引的术语数。但是,似乎字段长度永远不会是整数。例如,我看到一个文档的内容字段中有两个术语,但是Solr计算的内容字段长度实际上是2.56,而不是我期望的2。在Solr/Lucene中如何真正计算字段长度?

我指的是根据BM25相似度函数计算分数时使用的字段长度,但我认为正在为其他排名方案计算字段长度。

最佳答案

正如我在BM25Similarity的代码中看到的:

  public final long computeNorm(FieldInvertState state) {
    final int numTerms = discountOverlaps ? state.getLength() - state.getNumOverlap() : state.getLength();
    return encodeNormValue(state.getBoost(), numTerms);
  }

其中state#getLength()是:
  /**
   * Get total number of terms in this field.
   * @return the length
   */
  public int getLength() {
    return length;
  }

实际上,它是一个整数。请问您在哪里看到非整数值? SolrAdmin用户界面?在哪里?

现在,当您发布输出时,我找到了它的来源:
source

看看这个:
private Explanation explainTFNorm(int doc, Explanation freq, BM25Stats stats, NumericDocValues norms) {
    List<Explanation> subs = new ArrayList<>();
    subs.add(freq);
    subs.add(Explanation.match(k1, "parameter k1"));
    if (norms == null) {
      subs.add(Explanation.match(0, "parameter b (norms omitted for field)"));
      return Explanation.match(
          (freq.getValue() * (k1 + 1)) / (freq.getValue() + k1),
          "tfNorm, computed from:", subs);
    } else {
      float doclen = decodeNormValue((byte)norms.get(doc));
      subs.add(Explanation.match(b, "parameter b"));
      subs.add(Explanation.match(stats.avgdl, "avgFieldLength"));
      subs.add(Explanation.match(doclen, "fieldLength"));
      return Explanation.match(
          (freq.getValue() * (k1 + 1)) / (freq.getValue() + k1 * (1 - b + b * doclen/stats.avgdl)),
          "tfNorm, computed from:", subs);
    }
  }

因此,根据字段长度,它们输出:float doclen = decodeNormValue((byte)norms.get(doc));
 /** The default implementation returns <code>1 / f<sup>2</sup></code>
   * where <code>f</code> is {@link SmallFloat#byte315ToFloat(byte)}. */
  protected float decodeNormValue(byte b) {
    return NORM_TABLE[b & 0xFF];
  }

/** Cache of decoded bytes. */
  private static final float[] NORM_TABLE = new float[256];

  static {
    for (int i = 1; i < 256; i++) {
      float f = SmallFloat.byte315ToFloat((byte)i);
      NORM_TABLE[i] = 1.0f / (f*f);
    }
    NORM_TABLE[0] = 1.0f / NORM_TABLE[255]; // otherwise inf
  }

实际上,看看wikipedia这个文档应该是

10-06 05:49