Solr / Lucene Scorer

В настоящее время мы работаем над проверкой концепции для клиента, использующего Solr, и смогли настроить все функции, которые им нужны, кроме скоринга.

Проблема в том, что им нужны оценки, которые заставляют результаты падать в несколько сегментов:

  • Группа 1: точное соответствие по категории (оценка = 4)
  • Блок 2: точное совпадение имени (оценка = 3)
  • Блок 3: частичное совпадение по категории (оценка = 2)
  • Блок 4: частичное совпадение имени (оценка = 1)

Первое, что мы сделали, - это разработали собственный класс подобия, который будет возвращать правильную оценку в зависимости от поля и точного или частичного совпадения.

Единственная проблема сейчас в том, что когда документ совпадает как по категории, так и по названию, оценки суммируются.

Пример: поиск по запросу "ресторан" возвращает документы в категории "ресторан", в названии которых также есть слово "ресторан", и, таким образом, они получают оценку 5 (4 + 1), но они должны получить только 4.

Я предполагаю, что для этого нам потребуется разработать собственный класс Scorer, но мы не знаем, как включить его в Solr. Другой вариант - создать настраиваемую реализацию SortField, аналогичную RandomSortField, уже присутствующей в Solr.

Может быть, есть даже более простое решение, о котором мы не знаем.

Все предложения приветствуются!


person TFor    schedule 14.06.2010    source источник


Ответы (4)


Scorer - это часть запросов 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

Чтобы использовать свой собственный класс Query в Solr, вам необходимо реализовать свой собственный solr QueryParserPlugin, который использует ваш собственный QParser, который генерирует ваш ранее реализованный запрос lucene. Затем вы можете использовать его в Solr, указанном здесь:

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

Эта часть реализации должна оставаться простой, так как это всего лишь склеивающий код.

Наслаждайтесь взломом Solr!

person jeje    schedule 14.06.2010

You can override the logic solr scorer uses. Solr uses DefaultSimilarity class for scoring.

  • Make a class extending DefaultSimilarity and override the functions tf(), idf() etc according to your need:

    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.
  • Поместите банку в папку lib соответствующего индекса или ядра.
  • Измените schema.xml соответствующего индекса: <similarity class="<your package name>.CustomSimilarity"/>
  • Вы можете проверить различные факторы, влияющие на оценку здесь

    По вашему запросу вы можете создавать сегменты, если ваш счет находится в определенном диапазоне. Также прочтите об усилении полей, повышении качества документов и т. Д. Это может быть полезно в вашем случае.

    person ameykpatil    schedule 17.11.2011
    comment
    Это прекрасно работает. Чтобы добавить, версии до 4.0 допускают только глобальное сходство. 4.0+ позволяют схожесть по полю. (см. wiki.apache.org/solr/SchemaXml#Similarity) - person arun; 23.04.2013


    Спасибо за хорошие ответы выше. Просто добавив к ним, после настройки этого в 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"/>
    

    (Из этой ссылки: но имейте в виду, что координаты и queryNorm (= 1.0f) сейчас не реализованы, поэтому вы получите разные оценки для TF-IDF!)

    person arun    schedule 26.04.2013