Чтобы добиться некоторой степени отказоустойчивости с Solr, я начал использовать NGramFilterFactory
. Вот интересные моменты из schema.xml
:
<field name="text" type="text" indexed="true" stored="true"/>
<copyField source="text" dest="text_ngram" />
<field name="text_ngram" type="text_ngram" indexed="true" stored="false"/>
<fieldType name="text_ngram" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.KeywordTokenizerFactory" />
<filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="3" />
</analyzer>
</fieldType>
Я использую обработчик запросов EDisMax
практически со стандартной конфигурацией. Вот интересные строки из solrconfig.xml
:
<requestHandler name="/browse" class="solr.SearchHandler">
<lst name="defaults">
<!-- Query settings -->
<str name="defType">edismax</str>
<str name="qf">
name name_ngram^0.001
</str>
<str name="mm">100%</str>
<str name="q.op">AND</str>
...
Это отлично работает, однако дает мне много нерелевантных результатов. Используя возможности анализа Solr, я думаю, что отследил проблему по следующей причине:
Запрос разбит на NGrams. Затем Solr ищет токенизированный запрос в поле text
или один из NGrams в поле text_ngram
. Использование debug=query
приведет к выводу следующего parsedquery
при поиске "что-то":
(+DisjunctionMaxQuery(((text_ngram:som text_ngram:ome text_ngram:met text_ngram:eth text_ngram:thi text_ngram:hin text_ngram:ing) | text:something)))/no_coord
Если я правильно прочитал, это означает, что либо
- Один из NGrams должен соответствовать или
- Исходный запрос (токенизированный) должен соответствовать
Теперь он также найдет такие элементы, как «ethernet», поскольку один из NGrams (eth
) одинаков.
Мой вопрос: как я могу установить более высокий порог для совпадений NGram? Есть ли способ сказать «возврат элемента только в том случае, если не менее 90% NGrams из запроса совпадают»? Убедиться, что 100% совпадений NGrams не имеет смысла, поскольку это фактически убьет отказоустойчивость.
Еще один способ, о котором я подумал, заключался в том, чтобы возвращать только результаты, которые выше определенного порогового значения по отношению к лучшему результату. Это связано с тем, что элемент «что-то» будет иметь очень высокую релевантность по сравнению с «ethernet». Итак, есть ли способ подключиться к Solr, чтобы возвращать только результаты, которые имеют, например. не менее 1/100 балла лучшего результата? Я читал, что есть способ предоставить пользовательский HitCollector
, но я не смог найти никакой информации об этом.
Спасибо!