您可以覆盖 Lucene 评分。
扩展org.apache.lucene.search.DefaultSimilarity,定义您的自定义评分算法。
许多 DefaultSimilarity 方法您可能只想存根,例如 idf(只返回 1),以便更复杂的评分元素不会影响您的结果。
然后在 solr 中的 schema.xml 中添加一行,将其配置为使用您的评分类,例如:
<similarity class="com.mycompany.MySimilarity" />
这是一个页面,其中包含有关评分工作原理的一些信息,请在此处查看:Lucene Scoring。那里还有一些关于添加自定义功能的资源,这可能有助于组合一个可用的 Similarily 类。
不过,老实说,特别是如果您是 Lucene/Solr 的新手,那么获得一些默认评分的经验可能会更好。它工作得很好,你把它扔掉会删除很多有价值的功能。
编辑:
请注意,这提供了一种可能(虽然不是很漂亮)的方式来实现相似性。再往下看另一种方式。您仍然需要自定义相似度,但它更简单。
好吧,这里是一个刺。我还没有测试过它(现在还不能这样做),但也许它会为你指明正确的方向。
可能最简单的方法是为每个字段存储一个规范来编码术语的长度。为此,请覆盖 computeNorm,并返回取自第二个参数的长度的倒数。
为了计算您指定的精确评分,您需要访问匹配的查询词,或者它的长度。两者都不是很容易。您可能会找到一种方法,或者您可以手动将该值传递给相似性类。由于您只需要按照您指定的顺序获取值,因此说明您的要求的另一种方式是“从最短到最长的顺序结果”。我们已经用 computeNorm 完成了。
然后,您只需将其余部分存根,从而产生以下内容:
float computeNorm(String field, FieldInvertState state) {
int length = state.getOffset() - state.getPosition();
return 1.0 / (float)length;
}
float coord(int overlap, int maxOverlap) {
return 1;
}
float idf(int docFreq, int numDocs) {
return 1;
}
float tf(float freq) {
return 1;
}
float queryNorm(float sumOfSquaredWeights) {
return 1;
}
float sloppyFreq(int distance) {
return 1;
}
float lengthNorm(string fieldName, int numTerms) {
return 1;
}
注意:范数是在文档被索引时计算的,所以插入文档时必须使用这个相似度才能生效。查询时间为时已晚,无法设定标准。由于压缩,它也非常近似。
一种更简单的方法(也许):
你知道,现在我想起来了,因为相同的排序是通过从最短到最长排序来获得的,你可以在没有新的相似性类的复杂性的情况下做到这一点。当您添加文档时,您可以应用字段级提升来完成同样的事情。只需将这些术语中的每一个提高 1/length 或一些类似的方法。
如果插入 abcde,则对该字段应用 1/5 的提升。
完成此操作后,您甚至可以查询“term:abc*^3”,这将允许您获得之前指定的百分比分数(尽管效果几乎相同,只有一个查询词)。
如果您使用这样的提升得分,我认为您应该能够在您的 CustomSimilarity 中删除所有内容。在这种情况下,'idf' 和 'tf' 可能是您真正需要担心的全部覆盖。