如何在Lucene中搜索特殊字符(+;!\?:)
我想在索引中搜索特殊字符 我转义了查询字符串中的所有特殊字符,但当我在索引中的lucene上执行queryas+时,它将创建queryas+() 因此,它不搜索任何字段如何在Lucene中搜索特殊字符(+;!\?:),lucene,Lucene,我想在索引中搜索特殊字符 我转义了查询字符串中的所有特殊字符,但当我在索引中的lucene上执行queryas+时,它将创建queryas+() 因此,它不搜索任何字段 如何解决这个问题?“我的索引”包含这些特殊字符。如果您使用的是StandardAnalyzer,则将丢弃非字母字符。尝试使用空白分析器为相同的值编制索引,看看这是否保留了所需的字符。它也可以保留你不想要的东西:当你可以考虑编写自己的分析器时,这基本上意味着创建一个ToKeNoStk堆栈来完成你需要的处理。 例如,SimpleAn
如何解决这个问题?“我的索引”包含这些特殊字符。如果您使用的是
StandardAnalyzer
,则将丢弃非字母字符。尝试使用空白分析器为相同的值编制索引,看看这是否保留了所需的字符。它也可以保留你不想要的东西:当你可以考虑编写自己的分析器时,这基本上意味着创建一个ToKeNoStk堆栈来完成你需要的处理。
例如,SimpleAnalyzer
实现以下管道:
@Override
public TokenStream tokenStream(String fieldName, Reader reader) {
return new LowerCaseTokenizer(reader);
}
这只是降低了代币的大小写
StandardAnalyzer
的功能远不止于此:
/** Constructs a {@link StandardTokenizer} filtered by a {@link
StandardFilter}, a {@link LowerCaseFilter} and a {@link StopFilter}. */
@Override
public TokenStream tokenStream(String fieldName, Reader reader) {
StandardTokenizer tokenStream = new StandardTokenizer(matchVersion, reader);
tokenStream.setMaxTokenLength(maxTokenLength);
TokenStream result = new StandardFilter(tokenStream);
result = new LowerCaseFilter(result);
result = new StopFilter(enableStopPositionIncrements, result, stopSet);
return result;
}
您可以在org.apache.lucene.analysis
中混合和匹配这些组件和其他组件,或者您可以编写自己的专用TokenStream
实例,这些实例由自定义分析器包装到处理管道中
另一个需要注意的问题是,您正在使用哪种图表化工具CharTokenizer
是一个抽象类,指定用于标记文本字符串的机制。它被一些简单的分析器使用(但不被标准分析器使用)。Lucene有两个子类:一个LetterTokenizer
和一个WhitespaceTokenizer
。通过实现boolean-isTokenChar(char c)
方法,您可以创建自己的保留所需字符并在不保留字符的基础上断开的字符。对于作者来说,这可能不是实际情况,但能够搜索所需的特殊字符:
创建自定义分析器
使用它进行索引和搜索
例如,它如何为我工作:
import org.apache.lucene.analysis.Analyzer;
导入org.apache.lucene.analysis.custom.CustomAnalyzer;
导入org.apache.lucene.document.document;
导入org.apache.lucene.document.Field;
导入org.apache.lucene.document.TextField;
导入org.apache.lucene.index.DirectoryReader;
导入org.apache.lucene.index.IndexReader;
导入org.apache.lucene.index.IndexWriter;
导入org.apache.lucene.index.IndexWriterConfig;
导入org.apache.lucene.queryparser.classic.queryparser;
导入org.apache.lucene.search.*;
导入org.apache.lucene.store.RAMDirectory;
导入org.junit.Test;
导入java.io.IOException;
导入静态org.hamcrest.Matchers.equalTo;
导入静态org.junit.Assert.assertThat;
公共类LuceneSpecialCharactersSearchTest{
/**
*尝试通过每个特殊字符的子字符串分别搜索字符串的测试。
*/
@试验
public void testSpecialCharacterSearch()引发异常{
//给定
LuceneSpecialCharactersSearch服务=新的LuceneSpecialCharactersSearch();
String[]luceneSpecialCharacters=新字符串[]{“+”,“-”,“&&&-”,“| |”,“!”,“(“,”,“{”,“}”,“[”,“],“^”,“\”,“,“?”,“:”,“\”;
//什么时候
for(字符串特殊字符:luceneSpecialCharacters){
字符串实际值=service.search(“列表的特殊字符”+特殊字符);
//然后
资产(实际,相等(LuceneSpecialCharactersSearch.TEXT,带有特殊字符));
}
}
私有静态类LuceneSpecialCharactersSearch{
私有静态最终字符串文本,带有特殊字符=“这是特殊字符的列表+-&&&&&&&|!(){}[]^\”~?:\*”;
私人最终索引作者;
public LuceneSpecialCharactersSearch()引发异常{
文档=新文档();
添加(新文本字段(“正文”,带有特殊字符的文本,Field.Store.YES));
RAMDirectory=new RAMDirectory();
writer=newindexwriter(目录,newindexwriterconfig(buildAnalyzer());
编写者。添加文档(文档);
writer.commit();
}
公共字符串搜索(字符串查询字符串)引发异常{
try(IndexReader=DirectoryReader.open(writer,false)){
IndexSearcher search=新的IndexSearcher(阅读器);
String escapedQueryString=QueryParser.escape(queryString.toLowerCase();
Analyzer=buildAnalyzer();
QueryParser body QueryParser=新的QueryParser(“body”,分析器);
bodyQueryParser.setDefaultOperator(QueryParser.Operator.AND);
Query bodyQuery=bodyQueryParser.parse(escapedQueryString);
BooleanQuery查询=新建BooleanQuery.Builder()
.add(新的BooleanClause(bodyQuery,BooleanClause.occurrent.SHOULD))
.build();
TopDocs searchResult=searcher.search(查询,1);
返回searcher.doc(searchResult.scoreDocs[0].doc).getField(“body”).stringValue();
}
}
/**
*生成用于索引和搜索的分析器。
*/
私有静态分析器buildAnalyzer()引发IOException{
返回CustomAnalyzer.builder()
.withTokenizer(“空白”)
.addTokenFilter(“小写”)
.addTokenFilter(“标准”)
.build();
}
}
}
请举例说明您正在搜索的内容和创建的内容。“查询为+”是什么意思?我正在搜索像+!?这样的特殊字符?等等,我找到了解决办法。实际上,我们使用的是一些定制的分析器,由于应用了过滤器,它给出了blank查询(+())。但当我使用关键字分析器时,它起了作用。您是否使用相同的分析器进行索引和查询?请添加一个代码示例,描述您的确切查询以及在调用搜索之前如何处理它。