问题 Solr / Lucene得分手


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

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

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

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

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

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

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

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

欢迎所有建议!


7121
2018-06-14 08:21


起源



答案:


记分器是通过'权重'查询方法的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

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

享受黑客索尔!


3
2018-06-14 10:33





您可以覆盖逻辑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;
      }
    
    }
    


    3
    2017-11-17 10:04



    这很好用。只是要添加,4.0之前的版本只允许全局相似。 4.0+允许每场相似性。 (参考 wiki.apache.org/solr/SchemaXml#Similarity) - arun


    答案:


    记分器是通过'权重'查询方法的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

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

    享受黑客索尔!


    3
    2018-06-14 10:33





    您可以覆盖逻辑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;
      }
    
    }
    


    3
    2017-11-17 10:04



    这很好用。只是要添加,4.0之前的版本只允许全局相似。 4.0+允许每场相似性。 (参考 wiki.apache.org/solr/SchemaXml#Similarity) - arun


    我相信索尔的 DisMaxRequestHandler 可以为你做的伎俩。

    这是 霍斯曼对dismax的解释 和 Mark Miller对查询解析器的调查


    2
    2018-06-14 09:52





    谢谢你上面的好答案。在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
    

    谷歌搜索引导您 这个,只需在schema.xml中添加此行,该行将应用于其余字段:

    <similarity class="solr.SchemaSimilarityFactory"/>
    

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


    2
    2018-04-26 00:14