В этом случае проблема не в этом, ведь если вы используете что-то вроде StandardTokenizer, которое разбивается на маркеры, такие как дефисы, тогда пользователи, ищущие «баскетбольный мяч», будут соответствовать оригинальному тексту «Basket-Ball» (и vica-versa), поэтому проблем нет.
Вопрос идет между двумя словами и одним эквивалентом слова, например. «баскетбол» и «баскетбол». Вам в основном нужно обрабатывать синонимы (например, куртка/пальто или в вашем случае баскетбол/баскетбол).
Вы можете преодолеть это, создав список эквивалентных слов самостоятельно или используя словарь, например WordNet, и добавив либо индекс, либо поиск с синонимами для каждого термина. Solr имеет SynonymFilter, который вы, вероятно, можете использовать (см. Также here).
EDIT:
Вот код очень простой синоним фильтра я написал некоторое время назад. Синонимы не являются экстернализированными, но вы легко добавляете это сами.
public class SynonymFilter extends TokenFilter {
private static final Logger log = Logger.getLogger(SynonymFilter.class);
private Stack<Token> synStack = new Stack<Token>();
static CharArrayMap<String[]> synLookup = new CharArrayMap<String[]>(5, true);
static {
synLookup.put("basketball".toCharArray(), new String[]{"basket ball"});
synLookup.put("trainer".toCharArray(), new String[]{"sneaker"});
synLookup.put("burger".toCharArray(), new String[]{"hamburger"});
synLookup.put("bike".toCharArray(), new String[]{"bicycle", "cycle"});
}
// TODO reverse map all the syns to each other e.g. sneaker to trainer
protected SynonymFilter(TokenStream input) {
super(input);
}
@Override
public Token next(Token reusableToken) throws IOException {
if (synStack.size() > 0)
return synStack.pop();
Token nextToken = input.next(reusableToken);
if (nextToken != null) {
addSynonyms(nextToken);
}
return nextToken;
}
private void addSynonyms(Token nextToken) {
char[] word = Arrays.copyOf(nextToken.termBuffer(), nextToken.termLength());
String[] synonyms = synLookup.get(word);
if (synonyms != null) {
for (String s : synonyms) {
if (!equals(word, s)) {
char[] chars = s.toCharArray();
Token synToken = new Token(chars, 0, chars.length, nextToken.startOffset(), nextToken.endOffset());
synToken.setPositionIncrement(0);
synStack.add(synToken);
log.info("Found synonym: " + s + " for: " + new String(nextToken.term()));
}
}
}
}
public static boolean equals(char[] word, String subString) {
return equals(word, word.length, subString);
}
public static boolean equals(char[] word, int len, String subString) {
if (len != subString.length())
return false;
for (int i = 0 ; i < subString.length(); i++) {
if (word[len - i - 1] != subString.charAt(subString.length() - i - 1))
return false;
}
return true;
}
}
Ваши идентификаторы/телефонные номера хранятся в отдельном поле или они просто встречаются в тексте? – ffriend
нет смысла иллюстрировать ваш вопрос с примером, который не имеет большого отношения к вашей проблеме, так как это означает, что любые ответы не обязательно будут сосредоточены на том, что вы _активно пытаетесь сделать. В будущем продемонстрируйте проблему с реалистичным сценарием. – Joel