Это зависит от того, что вы подразумеваете под «специальными символами», и от того, какие другие требования вы можете иметь. Но следующее может дать вам то, что вам нужно, или указать правильное направление.
Все следующие примеры предполагают версию Lucene 8.4.1.
Basi c Пример
Начиная с очень точного c примера, который вы привели, где doc-size type
должен быть проиндексирован как docsize
и type
, вот специальный анализатор:
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.WhitespaceTokenizer;
import org.apache.lucene.analysis.pattern.PatternReplaceFilter;
import java.util.regex.Pattern;
public class MyAnalyzer extends Analyzer {
@Override
protected TokenStreamComponents createComponents(String fieldName) {
final Tokenizer source = new WhitespaceTokenizer();
TokenStream tokenStream = source;
Pattern p = Pattern.compile("\\-");
boolean replaceAll = Boolean.TRUE;
tokenStream = new PatternReplaceFilter(tokenStream, p, "", replaceAll);
return new TokenStreamComponents(source, tokenStream);
}
}
Это разбивает на пробельные символы, а затем удаляет дефисы, используя PatternReplaceFilter
. Это работает, как показано ниже (я использую 「и」 в качестве разделителей, чтобы показать, где пробелы могут быть частью входов / выходов):
Input text:
「doc-size type」
Output tokens:
「docsize」
「type」
ПРИМЕЧАНИЕ - это удалит все дефисы, которые стандартная клавиатура дефисы, но не такие вещи, как тире, тире и т. д. Эти стандартные дефисы будут удалены независимо от того, где они появляются в тексте (слова начинаются, слова заканчиваются сами по себе и т. Д. c).
Набор знаков препинания
Вы можете при необходимости измените шаблон, чтобы охватить больше знаков препинания, например:
Pattern p = Pattern.compile("[$^-]");
. Это делает следующее:
Input text:
「doc-size type $foo^bar」
Output tokens:
「docsize」
「type」
「foobar」
Все, что не является символом или Di git
Вы можете использовать следующее, чтобы удалить все, что не является символом или ди git:
Pattern p = Pattern.compile("[^A-Za-z0-9]");
Это делает следующее:
Input text:
「doc-size 123 %^&*{} type $foo^bar」
Output tokens:
「docsize」
「123」
「」
「type」
「foobar」
Обратите внимание, что это имеет одна пустая строка в результирующих тегах.
ПРЕДУПРЕЖДЕНИЕ: сработает ли вышеизложенное для вас, во многом зависит от ваших конкретных c, подробных требований. Например, вам может потребоваться выполнить дополнительные преобразования для обработки различий в верхнем / нижнем регистре, т. Е. Обычные вещи, которые обычно необходимо учитывать при индексировании текста.
Примечание по стандартному анализатору
The StandardAnalyzer
фактически действительно удаляет дефисы в словах (с некоторыми неясными исключениями). В своем вопросе вы упомянули, что он их не удаляет. Стандартный анализатор использует стандартный токенизатор. А стандартный токенизатор реализует правила Word Break из алгоритма сегментации текста Unicode, как указано здесь . Есть раздел, в котором обсуждается, как обрабатываются дефисы в словах.
Итак, Стандартный анализатор сделает это:
Input text:
「doc-size type」
Output tokens:
「doc」
「size」
「type」
Это должно работать как с поиском по doc
, так и doctype
- вопрос лишь в том, работает ли он достаточно хорошо для ваших нужд.
Я понимаю, что это может быть не тем, что вы хотите. Но если вам не придется создавать собственный анализатор, жизнь, вероятно, будет намного проще.