#solr
#solr
Вопрос:
Я пытаюсь добавить теги к предоставленному пользователем тексту, чтобы автоматически классифицировать статью.
Он работает довольно хорошо, за исключением слов с пробелами. Например, я хочу добавить тег «одежда», когда пользователь вводит следующие слова в таком порядке: «футболка» или «футболки». Предложение «моя футболка синяя» должно принести результат, поскольку «футболка» написана правильно в этом порядке, но ни «футболка моя рубашка», ни «моя рубашка» не должны возвращать результат.
Для этого у меня есть специальное ядро «теги». Я создаю пустое ядро с
/opt/solr/bin/solr create -c "tags"
и обновите основную схему с помощью curl
curl -X POST -H 'Content-type:application/json' --data-binary '{ "add-field-type" : { "name":"myShingleTextField", "class":"solr.TextField", "positionIncrementGap":"100", "analyzer" : { "tokenizer":{ "class":"solr.StandardTokenizerFactory" }, "filters":[ { "class":"solr.LowerCaseFilterFactory" }, { "class":"solr.ShingleFilterFactory", "maxShingleSize":"3", "outputUnigrams":"true" }, ]}} }' http://localhost:8983/solr/tags/schema
curl -X POST -H 'Content-type:application/json' --data-binary '{ "add-field": { "name":"keywords", "type":"myShingleTextField", "multiValued":true, "indexed":true, "stored":true, "required":true, "docValues":false } }' http://localhost:8983/solr/tags/schema
curl -X POST -H 'Content-type:application/json' --data-binary '{ "add-field": { "name":"results", "type":"string", "multiValued":true, "indexed":true, "stored":true, "required":true, "docValues":true } }' http://localhost:8983/solr/tags/schema
Затем я / обновляю его следующим (упрощенным) документом:
{ "add": { "doc": { "keywords": ["tee shirt", "tee shirts"], "results": ["clothes"] } }, "commit": { } }
Я, наконец, выполняю свой запрос:
/select?defType=dismaxamp;q=tee my shirtamp;qf=keywords
Он возвращает документ, в то время как я его не хочу («мой» между «футболкой» и «рубашкой»).
Может быть, это проблема с токенизатором или, может быть, запрос dismax — это не то, что мне нужно. Я попытался избежать кавычек или пробелов, изменив параметр mm на 2 (что вроде работает, но не позволяет сопоставлять одно слово) и другие настройки, которые не сработали.
Есть идеи?
Комментарии:
1. Звучит так, как будто вы хотите выполнить поиск по фразе, вы пробовали заключать
q=
аргумент в кавычки?2. Не совсем. Параметр «q» устанавливается в любое значение, введенное пользователем. Если пользователь введет «моя футболка синего цвета», я буду искать эту строку (в кавычках), и solr ничего не вернет, пока слова на футболке расположены правильно. Если я добавлю документ с одним словом, например keywords = «airmax» results =»shoes», он работает нормально.
3. Действует ли то же правило для более длинных предложений? Т.Е. Вы всегда ищете точные совпадения фраз с тем, что есть в индексе? Возможно, это решит фильтр shingle для запроса и отдельных токенов при индексации. Фильтр shingle при индексации будет генерировать
tee
,tee_my
,tee_my_shirt
,my_shirt
, в то время как индекс будет содержатьtee_shirt
. Ни один из них не сгенерирует совпадение. Индексация будет представлять собой keywordtokenizer со строчными буквами и регулярным выражением для замены пробелов на_
4.
Does the same rule hold for longer sentences? I.e. are you always looking for exact phrase matches against what's in the index?
Да, я запрашиваю solr с длинным предложением, и я хочу найти в нем ключевые слова (точное совпадение).The shingle filter on indexing would generate...
Я думаю, вы хотели ввести здесь «при запросе». Я не знал, что могу использовать фильтр shingle для запроса. Я думаю, что предложенное вами решение будет работать, спасибо за подсказку! Я проверю это (возможно, в эти выходные) и отмечу ваш ответ как действительный, если окажется, что вы правы. Еще раз спасибо!
Ответ №1:
Благодаря подсказкам @MatsLindth я нашел решение.
Во-первых, мне нужно было заменить пробелы в нескольких словах на ‘_’ и использовать KeywordTokenizerFactory tokenizer для их дословного сохранения. На стороне запроса мне пришлось указать параметр «tokenSeparator» как «_».
Итак, моя команда определения пользовательского типа поля теперь :
curl -X POST -H 'Content-type:application/json' --data-binary '{ "add-field-type" : { "name":"myShingleTextField", "class":"solr.TextField", "positionIncrementGap":"100", "indexAnalyzer": { "tokenizer":{ "class":"solr.KeywordTokenizerFactory" } }, "queryAnalyzer" : { "tokenizer":{ "class":"solr.StandardTokenizerFactory" }, "filters":[ { "class":"solr.LowerCaseFilterFactory" }, { "class":"solr.ShingleFilterFactory", "maxShingleSize":"3", "outputUnigrams":"true", "tokenSeparator":"_" }, ]}} }' http://localhost:8983/solr/tags/schema
Моя команда обновления теперь:
{ "add": { "doc": { "keywords": ["tee_shirt", "tee_shirts"], "results": ["clothes"] } }, "commit": { } }
Поэтому, когда я делаю :
/select?defType=dismaxamp;q=tee my shirtamp;qf=keywords
мы имеем
«футболка моя рубашка»
«футболка» «моя» «рубашка» (StandardTokenizerFactory LowerCaseFilterFactory)
«tee» «tee_my» «tee_my_shirt» «my» «my_shirt» «рубашка» (ShingleFilterFactory)
Ничто не соответствует ожидаемому, но запрос «моя футболка» выдает «tee_shirt», который, очевидно, соответствует «tee_shirt», ура!
Еще раз спасибо @MatsLindth и странице анализа Solr!