我最近创建了一个自定义TokenFilter,用于将CamelCased
的现有令牌拆分为单独的其他令牌。例如,短语MyClassName
将产生以下4个标记:
MyClassName
,My
,Class
,Name
代码如下:
private class CamelCaseFilter extends TokenFilter {
private final CharTermAttribute termAttribute = addAttribute(CharTermAttribute.class);
private final OffsetAttribute offsetAttribute = addAttribute(OffsetAttribute.class);
private final PositionIncrementAttribute posIncAttribute = addAttribute(PositionIncrementAttribute.class);
private boolean processing;
private int processingIndex;
private int processingCharPos;
private String[] splittedValues;
protected CamelCaseFilter(TokenStream input) {
super(input);
}
@Override
public boolean incrementToken() throws IOException {
if (!processing) {
if (!input.incrementToken()) {
return false;
}
posIncAttribute.setPositionIncrement(1);
splittedValues = splitCamelCase(termAttribute.toString());
if (splittedValues.length > 1) {
processing = true;
processingIndex = 0;
processingCharPos = 0;
}
return true;
}
String part = splittedValues[processingIndex];
termAttribute.setEmpty();
termAttribute.append(part);
offsetAttribute.setOffset(processingCharPos, processingCharPos + part.length());
processingCharPos += part.length();
processingIndex++;
if (processingIndex >= splittedValues.length) {
processing = false;
}
return true;
}
private static String[] splitCamelCase(String s) {
// TODO maybe replace with splitByCharacterTypeCamelCase from commons?
// http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/StringUtils.html#splitByCharacterTypeCamelCase%28java.lang.String%29
return s.split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z0-9])");
}
}
我的问题是,像这样使用PositionIncrementAttribute
是否正确(和必要)。 documentation说:
确定此令牌相对于词组搜索中使用的TokenStream中先前令牌的位置。
默认值为1。
一些常见用途是:
- 将其设置为零可将多个项放在同一位置。例如,当一个单词有多个词干时,这很有用。搜索包括任一词干在内的词组都将匹配。在这种情况下,除了第一个词根的增量外,所有其他增量都应设置为零:第一个实例的增量应为1。重复以零为增量的令牌也可以提高该令牌上的匹配分数。
- ...
但是,这与我的用例并不完全匹配。 Another part也说:
请注意,过滤出令牌的过滤器必须增加位置增量,以免生成损坏的令牌流图。
就我而言,我不会删除而是添加令牌。由于我保留了原始术语,而且还存储了其一部分,因此我认为将位置增量设置为零对于不增加新标记对搜索产生负面影响非常重要。是真的吗?还是我犯错了?