我正在使用 Lucene.NET 3.0.3
如何使用给定函数修改 SpellChecker(或一般查询)的评分?
具体来说,我希望 SpellChecker 对搜索词排列的任何结果进行评分高于其余建议,但我不知道应该在哪里完成。
我也会接受解释如何使用普通查询执行此操作的答案。我有这个功能,但我不知道将其设置为查询或过滤器或其他东西是否会更好。
我正在使用 Lucene.NET 3.0.3
如何使用给定函数修改 SpellChecker(或一般查询)的评分?
具体来说,我希望 SpellChecker 对搜索词排列的任何结果进行评分高于其余建议,但我不知道应该在哪里完成。
我也会接受解释如何使用普通查询执行此操作的答案。我有这个功能,但我不知道将其设置为查询或过滤器或其他东西是否会更好。
我认为解决此问题的最佳方法是在 SpellChecker 对象中使用自定义的比较器。
在此处查看默认比较器的源代码:
非常简单的东西,如果你已经有了比较两个字符串的算法,应该很容易扩展。
然后你可以使用设置它来使用你的比较器与SpellChecker.SetComparator
我想我在上一个问题中提到了为此使用过滤器的可能性,但我认为这不是正确的方法,多看一点。
编辑 - -
事实上,3.0.3 中没有 Comparator 可用,所以我相信您需要通过StringDistance对象访问评分。Comparator 会更好,因为已经应用了评分并将其传递给它以做你喜欢的事情。扩展 StringDistance 可能不太具体,因为您必须将规则作为分数的一部分应用。
您可能想要扩展LevensteinDistance(源代码),这是默认的 StringDistance 实现,但当然,您也可以随意尝试JaroWinklerDistance。对算法不是很熟悉。
首先,在从标准(父)实现的 getDistance 调用中获得基线距离后,您需要覆盖 getDistance 并在那里应用您的评分规则。
我可能会实现类似的东西(假设你有一个辅助方法boolean isPermutation(String, String)
:
class CustomDistance() extends LevensteinDistance{
float getDistance(String target, String other) {
float distance = super.getDistance();
if (isPermutation(target, other)) {
distance = distance + (1 - distance) / 2;
}
return distance;
}
}
为一个排列的结果计算一个接近 1 的分数的一半(也就是说,如果默认算法给出距离 = .6,这将返回距离 = .8,等等)。返回的距离必须介于 0 和 1 之间。我的示例只是可能的评分方法之一,但您可能需要稍微调整算法。我对简单地为所有排列返回 1.0 持谨慎态度,因为当使用“weiss”查看时,肯定会更喜欢“isews”而不是“weis”,并且它也会失去对不同排列的接近度进行排序的能力('在这种情况下, isews' 和 'wiess' 将与 'weiss' 相等匹配)。
拥有自定义 StringDistance 后,可以通过构造函数或使用 SpellChecker.setStringDistance 将其传递给SpellChecker
根据 femtoRgon 的建议,这就是我最终要做的事情:
public class PermutationDistance: SpellChecker.Net.Search.Spell.StringDistance
{
public PermutationDistance()
{
}
public float GetDistance(string target, string other)
{
LevenshteinDistance l = new LevenshteinDistance();
float distance = l.GetDistance(target, other);
distance = distance + ((1 - distance) * PermutationScore(target, other));
return distance;
}
public bool IsPermutation(string a, string b)
{
char[] ac = a.ToLower().ToCharArray();
char[] bc = b.ToLower().ToCharArray();
Array.Sort(ac);
Array.Sort(bc);
a = new string(ac);
b = new string(bc);
return a == b;
}
public float PermutationScore(string a, string b)
{
char[] ac = a.ToLower().ToCharArray();
char[] bc = b.ToLower().ToCharArray();
Array.Sort(ac);
Array.Sort(bc);
a = new string(ac);
b = new string(bc);
LevenshteinDistance l = new LevenshteinDistance();
return l.GetDistance(a, b);
}
}
然后:
_spellChecker.setStringDistance(new PermutationDistance());
List<string> suggestions = _spellChecker.SuggestSimilar(word, 10).ToList();