2

我正在使用 Lucene.NET 3.0.3

如何使用给定函数修改 SpellChecker(或一般查询)的评分?

具体来说,我希望 SpellChecker 对搜索词排列的任何结果进行评分高于其余建议,但我不知道应该在哪里完成。

我也会接受解释如何使用普通查询执行此操作的答案。我有这个功能,但我不知道将其设置为查询或过滤器或其他东西是否会更好。

4

2 回答 2

1

我认为解决此问题的最佳方法是在 SpellChecker 对象中使用自定义的比较器。

在此处查看默认比较器的源代码:

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-spellchecker/3.6.0/org/apache/lucene/search/spell/SuggestWordScoreComparator.java?av=f

非常简单的东西,如果你已经有了比较两个字符串的算法,应该很容易扩展。

然后你可以使用设置它来使用你的比较器与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

于 2012-12-03T20:41:08.657 回答
1

根据 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();
于 2012-12-03T22:10:55.097 回答