Solr возвращает вместе с корректными данным излишние данные
У меня есть Spring MVC проект. К нему прикручен Solr. В приложении есть возможность поиска работников(через Solr). Поиск работает по большей части корректно, можно найти пользователя с именем Иван введя соответственно Иван, либо не переключая англ. раскладку Bdfy. Пользователь выведется без проблем. Но существуют пользователи, при выводе которых одновременно выводятся и не подходящие по запросу пользователи. Например, если ввести Абдула, выведется сам Абдула, а так же несколько неподходящих пользователей. Вот пример с фронта:
public <T extends Index> IndexQueryResult<T> query(IndexQuery<T> indexQuery) throws IndexException {
Core core = getCore(indexQuery.getEntityClass());
try {
if (core == null)
throw new SolrServerException("Solr core is not defined");
SolrClient solr = solrConfiguration.getSolrClient(core);
String selectQuery = indexQuery.getQuery() == null
? "" : StringUtils.escapeCharacters(indexQuery.getQuery(), ESCAPE_CHARACTERS, '\\');
String spellcheckSuggestion = null;
if (indexQuery.isUseSpellcheck()) {
SolrQuery spellSelect = new SolrQuery(selectQuery);
spellSelect.setParam("spellcheck.q", selectQuery);
spellSelect.setParam("spellcheck", "on");
spellSelect.setRequestHandler("/spell");
QueryResponse spellResponse = solr.query(spellSelect, SolrRequest.METHOD.POST);
if (spellResponse.getSpellCheckResponse() != null) {
spellcheckSuggestion = spellResponse.getSpellCheckResponse().getCollatedResult();
}
}
// Other method code ...
}
Configs:
<requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
<lst name="defaults">
<str name="df">text_spell</str>
<!-- Solr will use suggestions from both the 'default' spellchecker
and from the 'wordbreak' spellchecker and combine them.
collations (re-written queries) can include a combination of
corrections from both spellcheckers -->
<str name="spellcheck.dictionary">default</str>
<!-- <str name="spellcheck.dictionary">wordbreak</str>-->
<str name="spellcheck">on</str>
<str name="spellcheck.extendedResults">true</str>
<str name="spellcheck.count">10</str>
<str name="spellcheck.alternativeTermCount">0</str>
<str name="spellcheck.maxResultsForSuggest">0</str>
<str name="spellcheck.collate">true</str>
<str name="spellcheck.collateExtendedResults">true</str>
<str name="spellcheck.maxCollationTries">10</str>
<str name="spellcheck.maxCollations">5</str>
</lst>
<arr name="last-components">
<str>spellcheck</str>
</arr>
</requestHandler>
Мой метод который преобразует слово исходя из одной раскладки в другую раскладку клавиатуры:
protected static final char[] LATINS = {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '`'};
// ... other code
protected void incrementTokenLogic() {
char[] buffer = charTermAttr.buffer();
if (buffer.length > 0) {
char[] newBuffer = new char[charTermAttr.length()];
for (int i = 0; i < charTermAttr.length(); i++) {
char ch = buffer[i];
if (LATIN_TO_CYR_MAP.containsKey(ch)) {
newBuffer[i] = LATIN_TO_CYR_MAP.get(ch);
} else {
newBuffer[i] = CYR_TO_LATIN_MAP.getOrDefault(ch, ch);
}
}
terms.add(newBuffer);
}
}
Проблема в том, что помимо того, что Solr выводит корректного пользователя, затем он берет слово "Абдула", переводит его на раскладку ENG -> F,lekf, и исходя из этого слова возвращает ненужных пользователей, которые не подходят. Из-за знака препинания, которое встречается в F,lekf.
Что можно в связи с этим предпринять?
Ответы (1 шт):
Лучше всего сделать как предложил Pak Uula - не добавлять к поисковым термам результаты конвертирования, если там есть что-либо кроме букв.
Другой вариант, который полезно знать: можно настроить query analyzer для того типа поля, которое вы используете для имени, чтобы он считал запятую алфавитно-цифровым символом и соответсвенно не токенизировал запросы с запятой.
Делается это так. Главное это добавить WordDelimiterFilterFactory в analyzer с типом query:
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<!-- ... пропускаю -->
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="1"
catenateNumbers="1"
catenateAll="0"
splitOnCaseChange="1"
types="wdftypes.txt"/>
<!-- ... тут еще могут быть фильтры -->
</analyzer>
</fieldType>
Ключевой момент тут это types="wdftypes.txt", остальные настройки смотрите под себя, тут я не знаю ваших остальных требований. wdftypes.txt это файл, в вашем случае такого вида:
, => ALPHANUM
Т.е. он указывает, что запятую считаем буквой. Его нужно положить в каталог conf.
