Solr поиск хэштага или упоминаний
Мы используем solr версии 3.5 для поиска в Tweets, я использую WordDelimiterFactory
со следующей настройкой, чтобы иметь возможность искать @username
или #hashtags
:
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0" splitOnNumerics="0" preserveOriginal="1" handleAsChar="@#"/>
Я увидел следующий патч, но, похоже, он не работает, как я и ожидал, я что-то упустил?
https://issues.apache.org/jira/browse/SOLR-2059
Но поиск @username
также возвращает результаты только для имени пользователя или #hashtag
- это просто результат возврата для hastag. Как я могу это достичь?
Целый тип поля:
<fieldType name="textnostem" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
<analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="1"
catenateNumbers="1"
catenateAll="0"
splitOnCaseChange="0"
splitOnNumerics="0"
preserveOriginal="1"
/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="1"
catenateNumbers="1"
catenateAll="0"
splitOnCaseChange="0"
splitOnNumerics="0"
preserveOriginal="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<fieldType name="textnostem" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
<analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="1"
catenateNumbers="1"
catenateAll="0"
splitOnCaseChange="0"
splitOnNumerics="0"
preserveOriginal="1"
/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="1"
catenateNumbers="1"
catenateAll="0"
splitOnCaseChange="0"
splitOnNumerics="0"
preserveOriginal="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="textnostem" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
<analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="1"
catenateNumbers="1"
catenateAll="0"
splitOnCaseChange="0"
splitOnNumerics="0"
preserveOriginal="1"
handleAsChar="@#"
/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="1"
catenateNumbers="1"
catenateAll="0"
splitOnCaseChange="0"
splitOnNumerics="0"
preserveOriginal="1"
handleAsChar="@#"
/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
Ответы
Ответ 1
ОК, поэтому, прочитав патч SOLR-2059, который вы упомянули, похоже, что они заменили атрибут handleAsChar
на WordDelimiterFactory на атрибут types
. Вот спецификация этого атрибута на странице "Анализаторы, токенизаторы и токены". Страница "Соль":
types = "wdfftypes.txt" позволяет настраивать токенизацию для этого фильтра. Файл должен существовать в каталоге solr/conf, а записи имеют форму (без кавычек) "% = > ALPHA" или "\ u002C = > DIGIT". Допустимыми типами являются: НИЖНЯЯ, ВЕРХНЯЯ, АЛЬФА, ЦИФРОВАЯ, АЛЬФАНАЯ, SUBWORD_DELIM.
Итак, если мы возьмем эту документацию, плюс пример файла из SOLR-2059, я бы рекомендовал следующее:
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0" splitOnNumerics="0" preserveOriginal="1" types="twittertypes.txt"/>
Затем определите файл twittertypes.txt следующим образом и поместите его в ту же папку, что и файл schema.xml в вашем экземпляре Solr (возможно, в папке conf).
# A customized type mapping for WordDelimiterFilterFactory
# the allowable types are: LOWER, UPPER, ALPHA, DIGIT, ALPHANUM, SUBWORD_DELIM
#
# the default for any character without a mapping is always computed from
# Unicode character properties
# Map the $, %, '.', and ',' characters to DIGIT
# This might be useful for financial data.
@ => ALPHA
\u0023 => ALPHA
Обратите внимание, что вам нужно использовать символ Unicode (UTF-8) для символа хэша, поскольку он рассматривается как комментарий в текстовом файле.
В соответствии со всей документацией это должно исправить вашу проблему и обработать символы # и @как альфа-символы, которые будут обеспечивать поведение, которое вы ищете.
Ответ 2
Вы также можете создать собственный токенайзер, который будет анализировать имена пользователей и хэштеги как специальные токены. Затем вы можете добавить пользовательский фильтр, который нормализует регистр этих имен пользователей и хэштегов (учитывая, что они не чувствительны к регистру), оставляя остальные токены без изменений:
<fieldType name="text_twitter" class="solr.TextField" positionIncrementGap="100" multiValued="true">
<analyzer type="index">
<tokenizer class="org.opentapioca.analysis.twitter.TwitterTokenizerFactory" />
<filter class="org.opentapioca.analysis.twitter.TwitterLowercaseFilterFactory" />
</analyzer>
<analyzer type="query">
<tokenizer class="org.opentapioca.analysis.twitter.TwitterTokenizerFactory" />
<filter class="org.opentapioca.analysis.twitter.TwitterLowercaseFilterFactory" />
</analyzer>
</fieldType>