我试图找出我应该做什么来索引包含“。”的关键字。
ex:this.name
我想索引条款:this和我的索引中的名字。
我使用StandardAnalyser。我尝试扩展WhitespaceTokensizer或扩展TokenFilter,但我不确定我是否在正确的方向。
如果我使用StandardAnalyser,我将获得“this.name”作为关键字,这不是我想要的,但分析师会为我正确地完成其余工作。
答案 0 :(得分:5)
您可以将CharFilter放在StandardTokenizer前面,将句点和下划线转换为空格。 MappingCharFilter将起作用。
这里的MappingCharFilter添加到精简的StandardAnalyzer中(参见原始的4.1版本here):
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.charfilter.MappingCharFilter;
import org.apache.lucene.analysis.charfilter.NormalizeCharMap;
import org.apache.lucene.analysis.core.LowerCaseFilter;
import org.apache.lucene.analysis.core.StopAnalyzer;
import org.apache.lucene.analysis.core.StopFilter;
import org.apache.lucene.analysis.standard.StandardFilter;
import org.apache.lucene.analysis.standard.StandardTokenizer;
import org.apache.lucene.analysis.util.StopwordAnalyzerBase;
import org.apache.lucene.util.Version;
import java.io.IOException;
import java.io.Reader;
public final class MyAnalyzer extends StopwordAnalyzerBase {
private int maxTokenLength = 255;
public MyAnalyzer() {
super(Version.LUCENE_41, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
}
@Override
protected TokenStreamComponents createComponents
(final String fieldName, final Reader reader) {
final StandardTokenizer src = new StandardTokenizer(matchVersion, reader);
src.setMaxTokenLength(maxTokenLength);
TokenStream tok = new StandardFilter(matchVersion, src);
tok = new LowerCaseFilter(matchVersion, tok);
tok = new StopFilter(matchVersion, tok, stopwords);
return new TokenStreamComponents(src, tok) {
@Override
protected void setReader(final Reader reader) throws IOException {
src.setMaxTokenLength(MyAnalyzer.this.maxTokenLength);
super.setReader(reader);
}
};
}
@Override
protected Reader initReader(String fieldName, Reader reader) {
NormalizeCharMap.Builder builder = new NormalizeCharMap.Builder();
builder.add(".", " ");
builder.add("_", " ");
NormalizeCharMap normMap = builder.build();
return new MappingCharFilter(normMap, reader);
}
}
这是一个快速测试,以证明它有效:
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.BaseTokenStreamTestCase;
public class TestMyAnalyzer extends BaseTokenStreamTestCase {
private Analyzer analyzer = new MyAnalyzer();
public void testPeriods() throws Exception {
BaseTokenStreamTestCase.assertAnalyzesTo
(analyzer,
"this.name; here.i.am; sentences ... end with periods.",
new String[] { "name", "here", "i", "am", "sentences", "end", "periods" } );
}
public void testUnderscores() throws Exception {
BaseTokenStreamTestCase.assertAnalyzesTo
(analyzer,
"some_underscore_term _and____ stuff that is_not in it",
new String[] { "some", "underscore", "term", "stuff" } );
}
}
答案 1 :(得分:0)
如果我理解正确,你需要使用一个去除点的标记器 - 也就是说,任何包含点的名称都应该在那一点被拆分(“here.i.am”变成“here”+“i “+”am“)。
答案 2 :(得分:0)
你被行为documented here抓住了:
但是,没有空格的点被视为令牌的一部分。
StandardTokenizer
引入了一些比你可能没有寻找的更复杂的解析规则。特别是,这一点旨在防止URL,IP,标识符等的标记化。更简单的实现可能适合您的需求,如LetterTokenizer
。
如果这不能满足您的需求(并且最终可能会将婴儿扔出洗澡水),那么您可能需要自己修改StandardTokenizer
,这是Lucene明确鼓励的文档:
许多应用程序都有特定的tokenizer需求。如果此tokenizer不适合您的应用程序,请考虑将此源代码目录复制到您的项目并维护您自己的基于语法的tokenizer。
答案 3 :(得分:0)
Sebastien Dionne:我仍然想知道如何将一个标记分成多个部分,并将它们全部索引
您可能需要编写自定义分析器。
Analyzer是Tokenizer和可能的TokenFilter实例链的组合。
Tokenizer:接收您传递的输入文本,可能是java.io.Reader。它
只是打破了文本。不改变,只是打破它。
TokenFilter:获取Tokenizer发出的令牌,添加/删除/修改令牌并逐个发出相同的内容,直到完成所有操作。
如果它根据需求替换具有多个令牌的令牌,则缓冲区全部将它们逐个发送给索引器。
您可能会检查以下资源,遗憾的是,您可能需要注册试用会员资格。
通过编写自定义分析器,您可以按照自己的方式细分文本。您甚至可以使用一些现有的组件,如LowercaseFilter。幸运的是,如果您无法找到内置或网络上的分析器,Lucene可以实现一些分析器。