【问题标题】:solr/lucene scoring by percentage of text matched?solr/lucene 按匹配文本的百分比评分?
【发布时间】:2012-11-02 04:23:26
【问题描述】:

对 Solr/Lucene 来说相当陌生。我有一个简单的要求,不确定配置 solr 是否容易做到这一点。

假设所有文档只有一个文本字段,未标记。

当查询进来时,我希望结果按匹配(包含)文本的百分比排序。百分比由len(query)/len(matched text field)计算

例如,有三个文档,文本字段如下:
doc1: abcdefghij
doc2:abcdefgh
3:ABC

如果搜索词是“cde”,则匹配文档 1 和文档 2(文本字段包含搜索词)。 对于文档 1,匹配百分比 = 3/10=30%
对于文档 2,匹配百分比 = 3/8=37.5%

所以结果应该是:
doc2
文档1

这有意义吗?如何使用 solr 实现?

谢谢。

【问题讨论】:

    标签: solr lucene


    【解决方案1】:

    您可以覆盖 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' 可能是在这种情况下您真正需要担心的全部覆盖。

    【讨论】:

    • 您能否添加更多关于用户如何通过覆盖相似性类来处理特定问题的信息?
    • @femtoRgon,感谢您的回复。是否有任何示例显示如何覆盖评分?是的,我完全理解默认评分效果很好。这是一个项目的业务需求,我想看看 Solr 是否可以处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 2018-04-13
    • 2015-06-22
    • 2021-02-05
    • 2021-05-07
    • 1970-01-01
    相关资源
    最近更新 更多