![](/img/trans.png)
[英]What is the difference between query time boost and field boost in lucene 6.0.1?
[英]Custom lucene scoring - Dot product between field boost and query boost
我想将Lucene与以下评分逻辑一起使用:在索引文档时,我想为每个字段设置一个得分/权重。 查询索引时,我想为每个查询词设置得分/权重。
我将永远不会索引或查询具有相同字段的许多实例–在每个查询(文档)中,将有0-1个具有相同字段名称的实例。 我的字段/查询词未进行分析-它们已经由一个标记组成。
我希望分数只是查询字段与文档字段之间具有相同值的点积。
例如:
格式为(栏位名称)(栏位值)(栏位分数)
查询:
1 AA 0.1
7 BB 0.2
8 CC 0.3
文件1:
1 AA 0.2
2 DD 0.8
7 CC 0.999
10 FFF 0.1
文件2:
7 BB 0.3
8 CC 0.5
分数应为:
得分(q,d1)= FIELD_1_SCORE_Q * FILED_1_SCORE_D1 = 0.1 * 0.2 = 0.02
得分(q,d2)= FIELD_7_SCORE_Q * FILED_7_SCORE_D2 + FIELD_8_SCORE_Q * FILED_8_SCORE_D2 =(0.2 * 0.3)+(0.3 * 0.5)
实施它的最佳方法是什么? 在准确性和性能方面(我不需要TF和IDF计算)。
我目前通过对字段和查询字词设置增强来实现它。 然后,我覆盖DefaultSimilarity类,并在建立索引/查询之前将其设置为默认值:
public class MySimilarity extends DefaultSimilarity {
@Override
public float computeNorm(String field, FieldInvertState state) {
return state.getBoost();
}
@Override
public float queryNorm(float sumOfSquaredWeights) {
return 1;
}
@Override
public float tf(float freq) {
return 1;
}
@Override
public float idf(int docFreq, int numDocs) {
return 1;
}
@Override
public float coord(int overlap, int maxOverlap) {
return 1;
}
}
并且基于http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/scoring.html,这应该可行。
问题:
这是我的代码的一部分:
indexSearcher = new IndexSearcher(IndexReader.open(directory, true));
TopScoreDocCollector collector = TopScoreDocCollector.create(iTopN, true);
indexSearcher.search(query, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
for (int i = 0; i < hits.length; ++i) {
int docId = hits[i].doc;
Document d = indexSearcher.doc(docId);
double score = hits[i].score;
String id = d.get(FIELD_ID);
Explanation explanation = indexSearcher.explain(query, docId);
}
谢谢!
您可以解决几件事:
您没有在粘贴的代码段中设置自定义相似性,请参见IndexSearcher#setSimilarity ,
当freq等于0时,实现相似性的“ tf”方法应返回0。
此外,您应谨慎使用索引时间提升。 由于它们是在单个字节上编码的,因此可能会有一些精度损失,请参阅《 Lucene》,为什么我的增强文档和未增强文档的得分相同? 。
索引时间提升的一种替代方法是在不同的数字字段中索引提升值,然后使用CustomScoreQuery和float FieldCacheSource在分数中利用这些提升。
找出答案-效果很好!
受Lucene邮件列表中的另一个线程(有关CustomScoreQuery的问题)的启发,我正在使用此解决方案,该解决方案运行得很好(有一个缺点):
我发现我的某些问题是由于我的假设是错误的:
我确实有许多具有相同字段ID的字段/查询术语。
这破坏了我的方法,因为查询提升已聚合并且我的计算是错误的。
我所做的是在索引编制过程中,将字段值添加到了字段ID(由“ _”连接),并在字段值中使用了所需的分数。
在搜索时,我使用具有复杂字段ID的简单FieldScoreQuery(按原样,无需修改)。
在这里,我仍然可以使用setBoost来设置分数,因为现在我的字段是唯一的。
从逻辑上讲,这是完美的选择-使用Lucene的点积。
缺点-许多许多不同类型的字段。
重要:
由于我没有使用索引文档字段的规范,因此权重是该字段的值,因此我现在使用以下方法索引这些字段:
Field field = new Field(field_name, Float.toString(weight), Store.YES, Index.NOT_ANALYZED_NO_NORMS);<br>
而且内存使用率已恢复正常...
非常酷!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.