Java Lucene和太长的代币
我正在使用Java Lucene和太长的代币,java,lucene,Java,Lucene,我正在使用Lucene开发一个索引器,上周在代码中添加了存储TermVectors,这样我就可以尝试反馈和其他有趣的东西。在存储术语向量的这一步之后,我开始出现以下错误: java.lang.IllegalArgumentException:文档至少包含一个 字段中的巨大术语=“f_common.document.text”(其UTF8编码 大于最大长度32766),所有这些都被跳过。 请更正分析器,使其不产生此类术语。前缀 第一个巨大的术语是:“[34,60,97,99,114,101,58,
Lucene
开发一个索引器,上周在代码中添加了存储TermVectors
,这样我就可以尝试反馈和其他有趣的东西。在存储术语向量的这一步之后,我开始出现以下错误:
java.lang.IllegalArgumentException:文档至少包含一个
字段中的巨大术语=“f_common.document.text”(其UTF8编码
大于最大长度32766),所有这些都被跳过。
请更正分析器,使其不产生此类术语。前缀
第一个巨大的术语是:“[34,60,97,99,114,101,58,98,
108, 111, 99, 107, 62, 32, 32, 32, 60, 100, 105, 118, 32, 97, 99,
114、101、58、100、101、102、61]…,原始消息:字节可以是
长度不超过32766;有34444个
好的,没问题。(好吧,死在超长的令牌上对我来说就像一个bug,但这是4.8中有意识的API迁移。)因此我添加了以下AnalyzerWrapper
来解决这个问题:
import java.io.IOException;
import java.io.StringReader;
import java.util.HashSet;
import java.util.Set;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.AnalyzerWrapper;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.miscellaneous.LengthFilter;
import org.apache.lucene.index.IndexWriter;
/*
* Lucene's IndexWriter.addDocument() will pitch an exception if the document contains a token that is too long.
* I would rather just drop long tokens.
*/
public class SafetyAnalyzer extends AnalyzerWrapper {
private Analyzer baseAnalyzer;
public SafetyAnalyzer(Analyzer baseAnalyzer) {
super(Analyzer.PER_FIELD_REUSE_STRATEGY);
this.baseAnalyzer = baseAnalyzer;
}
@Override
public void close() {
baseAnalyzer.close();
super.close();
}
@Override
protected Analyzer getWrappedAnalyzer(String fieldName) {
return baseAnalyzer;
}
@Override
protected TokenStreamComponents wrapComponents(String fieldName, TokenStreamComponents components) {
TokenStream ts = components.getTokenStream();
LengthFilter drop_long_tokens = new LengthFilter(ts, 0, IndexWriter.MAX_TERM_LENGTH);
return new TokenStreamComponents(components.getTokenizer(), drop_long_tokens);
}
}
这将丢弃IndexWriter
将吐出的长标记。这会像这样包装其他分析器:
public Analyzer getDefaultIndexAnalyzer() throws Exception {
if (defaultIndexAnalyzer == null) {
String defaultAnalyzerName = getConfig("LUCENE_INDEX_ANALYZER_DEFAULT");
if (defaultAnalyzerName == null)
defaultAnalyzerName = "org.apache.lucene.analysis.standard.StandardAnalyzer";
defaultIndexAnalyzer = new SafetyAnalyzer((Analyzer)Class.forName(defaultAnalyzerName).newInstance());
}
return defaultIndexAnalyzer;
}
只是,它不起作用。我仍然在这些令牌上获得IllegalArgumentExceptions
。我能找到的唯一解决方案是在writer.addDocument()
上捕获IAE
是否写入分析器错误?字段长度小于IndexWriter的字符限制,但超过了字节限制
LengthFilter
根据令牌的字符长度(UTF-16代码单位)过滤掉令牌IndexWriter.MAX_TERM_LENGTH
则以UTF-8编码字节为单位
这个过滤器应该满足您的需要。与LengthFilter
的工作原理相同,因此应该可以很容易地将类似的内容放入SafetyAnalyzer
(它实际上只是LengthFilter
的一个副本,带有修改的accept()
方法):
import java.nio.CharBuffer;
导入java.nio.charset.charset;
导入org.apache.lucene.analysis.TokenStream;
导入org.apache.lucene.analysis.util.FilteringTokenFilter;
导入org.apache.lucene.analysis.tokenattributes.CharterMatAttribute;
公共最终类ByteLengthFilter扩展FilteringTokenFilter{
私人最终整数分钟;
私人最终整数最大值;
私有最终CharterMatAttribute termAtt=addAttribute(charterMatAttribute.class);
public ByTeleneghtFilter(令牌流输入、最小整数、最大整数){
超级(in),;
如果(最小值<0){
抛出新的IllegalArgumentException(“最小长度必须大于或等于零”);
}
如果(最小值>最大值){
抛出新的IllegalArgumentException(“最大长度不得大于最小长度”);
}
this.min=min;
this.max=max;
}
@凌驾
公共布尔接受(){
final int len=Charset.forName(“UTF-8”).encode(CharBuffer.wrap(termAtt)).remaining();
return(len>=min&&len字段的长度小于IndexWriter的字符限制,但超过了字节限制。LengthFilter
根据标记的字符长度(UTF-16代码单位)过滤掉标记。IndexWriter.MAX\u TERM\u length
则是UTF-8编码字节
此筛选器应该满足您的需要。其工作原理与LengthFilter
相同,因此可以很容易地将类似的内容放入SafetyAnalyzer
(它实际上只是LengthFilter
的一个副本,带有修改的accept()
方法):
import java.nio.CharBuffer;
导入java.nio.charset.charset;
导入org.apache.lucene.analysis.TokenStream;
导入org.apache.lucene.analysis.util.FilteringTokenFilter;
导入org.apache.lucene.analysis.tokenattributes.CharterMatAttribute;
公共最终类ByteLengthFilter扩展FilteringTokenFilter{
私人最终整数分钟;
私人最终整数最大值;
私有最终CharterMatAttribute termAtt=addAttribute(charterMatAttribute.class);
public ByTeleneghtFilter(令牌流输入、最小整数、最大整数){
超级(in),;
如果(最小值<0){
抛出新的IllegalArgumentException(“最小长度必须大于或等于零”);
}
如果(最小值>最大值){
抛出新的IllegalArgumentException(“最大长度不得大于最小长度”);
}
this.min=min;
this.max=max;
}
@凌驾
公共布尔接受(){
final int len=Charset.forName(“UTF-8”).encode(CharBuffer.wrap(termAtt)).remaining();
返回(len>=min&&len谢谢你提供的线索。也许最好换一种方式,计算我希望能够为即将到来的数据保留多少字符。我将尝试两种方式,看看会发生什么。@IanSoboroff-当然,你可以安全地将其限制在IndexWriter.MAX\u TERM\u LENGTH/4
,我相信。谢谢你提供的线索最好换一种方式,计算我希望能为即将到来的数据保留多少个字符。我将尝试两种方法,看看会发生什么。@IanSoboroff-当然,我相信您可以安全地将其限制为IndexWriter.MAX\u TERM\u LENGTH/4
。
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.util.FilteringTokenFilter;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
public final class ByteLengthFilter extends FilteringTokenFilter {
private final int min;
private final int max;
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
public ByteLengthFilter(TokenStream in, int min, int max) {
super(in);
if (min < 0) {
throw new IllegalArgumentException("minimum length must be greater than or equal to zero");
}
if (min > max) {
throw new IllegalArgumentException("maximum length must not be greater than minimum length");
}
this.min = min;
this.max = max;
}
@Override
public boolean accept() {
final int len = Charset.forName("UTF-8").encode(CharBuffer.wrap(termAtt)).remaining();
return (len >= min && len <= max);
}
}