Солр/Луценский бомбардир
В настоящее время мы работаем над доказательством концепции для клиента, использующего Solr, и смогли настроить все функции, которые они хотят, за исключением скоринга.
Проблема в том, что они хотят, чтобы результаты попадали в ведра:
- Ковш 1: точное соответствие по категории (оценка = 4)
- Ведро 2: точное совпадение имени (оценка = 3)
- Ведро 3: частичное совпадение по категории (оценка = 2)
- Ведро 4: частичное совпадение имени (оценка = 1)
Первое, что мы сделали, это разработать собственный класс подобия, который вернет правильный результат в зависимости от поля и точного или частичного соответствия.
Единственная проблема теперь в том, что когда документ соответствует как категории, так и имени, баллы добавляются вместе.
Пример: поиск "ресторана" возвращает документы в ресторан категории, в котором также есть слово ресторан на свое имя и, таким образом, получить оценку 5 (4 + 1), но они должны получить только 4.
Я предполагаю, что для этого нам нужно разработать собственный класс Scorer, но мы не имеем понятия о том, как включить его в Solr.
Другим вариантом является создание пользовательской реализации SortField, аналогичной RandomSortField, уже присутствующей в Solr.
Возможно, есть еще более простое решение, о котором мы не знаем.
Приветствуем все предложения!
Ответы
Ответ 1
Счетчик - это части запросов 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!
Ответ 2
Вы можете переопределить использование логического контроллера. 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;
}
}
После создания класса компилируйте и создайте банку.
Поместите банку в папку lib соответствующего индекса или ядра.
Измените schema.xml соответствующего индекса:
<similarity class="<your package name>.CustomSimilarity"/>
Вы можете проверить различные факторы, влияющие на оценку здесь
Для вашего требования вы можете создавать ведра, если ваш счет находится в определенном диапазоне. Также читайте о повышении поля, повышении документа и т.д. Это может быть полезно в вашем случае.
Ответ 3
Я считаю, что Solr DisMaxRequestHandler может сделать трюк для вас.
Ниже приведены объяснение хесманов о дефектах и Исследование Марка Миллера парсеров запросов.
Ответ 4
Спасибо за хорошие ответы выше. Просто добавив к ним, установив это в 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!)