Solr / Lucene得分手

时间:2010-06-14 08:21:21

标签: lucene solr

我们目前正在为使用Solr的客户进行概念验证,并且能够配置他们想要的所有功能,除了得分。

问题是他们想要得分使得结果落在桶中:

  • 第1栏:类别完全匹配(得分= 4)
  • 第2栏:名称上的完全匹配(得分= 3)
  • 第3栏:类别(得分= 2)的部分匹配
  • 第4栏:名称上的部分匹配(得分= 1)

我们做的第一件事就是开发一个自定义相似度类,它会根据字段和精确或部分匹配返回正确的分数。

现在唯一的问题是,当文档在类别和名称上匹配时,分数会加在一起。

示例:搜索“餐馆”会返回类别餐厅中的文档,这些文档的名称中也包含“餐馆”字样,因此得分为5(4 + 1),但只能得到4分。

我认为为了实现这个目的,我们需要开发一个自定义的Scorer类,但我们不知道如何在Solr中加入它。 另一种选择是创建一个类似于Solr中已经存在的RandomSortField的自定义SortField实现。

也许甚至还有一个我们不了解的简单解决方案。

欢迎所有建议!

4 个答案:

答案 0 :(得分:3)

通过'权重'查询方法,得分者是lucene查询的一部分。

简而言之,框架调用Query.weight(..)。scorer(..)。看看

http://lucene.apache.org/java/2_4_0/api/org/apache/lucene/search/Query.html

http://lucene.apache.org/java/2_4_0/api/org/apache/lucene/search/Weight.html

http://lucene.apache.org/jva/2_4_0/api/org/apache/lucene/search/Scorer.html

要在Solr中使用您自己的Query类,您需要实现自己的solr QueryParserPlugin,它使用您自己的QParser生成以前实现的lucene Query。然后,您可以在此处指定的Solr中使用它:

http://wiki.apache.org/solr/SolrPlugins#QParserPlugin

这部分实现应该保持简单,因为这只是一些粘合代码。

享受黑客Solr!

答案 1 :(得分:3)

您可以覆盖逻辑solr得分者使用。 Solr使用DefaultSimilarity类进行评分。

  • 创建一个扩展DefaultSimilarity的类,并根据需要覆盖函数tf(),idf()等:

    public class CustomSimilarity extends DefaultSimilarity {
    
      public CustomSimilarity() {
        super();
      }
    
      public float tf(int freq) {
        //your code  
        return (float) 1.0;
      }
    
      public float idf(int docFreq, int numDocs) {
        //your code
        return (float) 1.0;
      }
    
    }
    

  • 创建类后编译并制作一个jar。
  • 将jar放在相应索引或核心的lib文件夹中。
  • 更改相应索引的schema.xml: <similarity class="<your package name>.CustomSimilarity"/>
  • 您可以查看影响得分的各种因素here

    根据您的要求,如果您的分数在特定范围内,您可以创建存储桶。还可以阅读有关现场提升,文档提升等信息。这可能对您的情况有所帮助。

    答案 2 :(得分:2)

    答案 3 :(得分:2)

    感谢上面的好答案。在Solr 4.2.1中进行设置后,只需添加它们,即允许每个字段的相似性。 (在Solr 4之前,您只能改变全局所有字段的相似性。)

    假设我们希望Solr不对特定字段使用逆文档频率(idf) - 我们应该为此编写自己的自定义相似度,如上所述:

    package com.mycompany.similarity;
    
    import org.apache.lucene.search.similarities.DefaultSimilarity;
    
    public class NoIDFSimilarity extends DefaultSimilarity
    {
        @Override
        public float idf(long docFreq, long numDocs)
        {
            return 1.0f;
        }
    
        @Override
        public String toString()
        {
            return "NoIDFSimilarity";
        }
    }
    

    然后在我们的schema.xml中定义一个新的fieldType:

    <fieldType name="int_no_idf" 
               class="solr.TrieIntField" 
               precisionStep="0" 
               positionIncrementGap="0" 
               omitNorms="true">
        <similarity class="com.mycompany.similarity.NoIDFSimilarity"/>
    </fieldType>
    

    并在像这样的字段上使用它:

    <field name="tag_id_no_idf" 
           type="int_no_idf" 
           indexed="true" 
           stored="false" 
           multiValued="true" />
    

    如果我们只做了这么多,那么你将得到以下例外:

    SEVERE: Unable to create core: SimilarList
    org.apache.solr.common.SolrException: FieldType 'int_no_idf' is configured with a similarity, but the global similarity does not support it: class org.apache.solr.search.similarities.DefaultSimilarityFactory
        at org.apache.solr.schema.IndexSchema.readSchema(IndexSchema.java:466)
        at org.apache.solr.schema.IndexSchema.<init>(IndexSchema.java:122)
        at org.apache.solr.core.CoreContainer.createFromLocal(CoreContainer.java:1018)
        at org.apache.solr.core.CoreContainer.create(CoreContainer.java:1051)
        at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:634)
        at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:629)
        at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
        at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
    Apr 25, 2013 5:02:08 PM org.apache.solr.common.SolrException log
    SEVERE: null:org.apache.solr.common.SolrException: Unable to create core: SimilarList
        at org.apache.solr.core.CoreContainer.recordAndThrow(CoreContainer.java:1672)
        at org.apache.solr.core.CoreContainer.create(CoreContainer.java:1057)
        at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:634)
        at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:629)
        at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
        at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
    Caused by: org.apache.solr.common.SolrException: FieldType 'int_no_idf' is configured with a similarity, but the global similarity does not support it: class org.apache.solr.search.similarities.DefaultSimilarityFactory
        at org.apache.solr.schema.IndexSchema.readSchema(IndexSchema.java:466)
        at org.apache.solr.schema.IndexSchema.<init>(IndexSchema.java:122)
        at org.apache.solr.core.CoreContainer.createFromLocal(CoreContainer.java:1018)
        at org.apache.solr.core.CoreContainer.create(CoreContainer.java:1051)
        ... 10 more
    

    Google搜索引导您this,因此只需在schema.xml中添加此行,该行将应用于其他字段:

    <similarity class="solr.SchemaSimilarityFactory"/>
    

    (从该链接:但请记住,coord和queryNorm(= 1.0f)现在没有实现,因此您将获得TF-IDF的不同分数!)