java使用Lucene解析搜索查询,并在此基础上构建Hibernate条件
需求是在单独一个表中保留的有限数量的字段上构建简化的搜索功能。使用Solr或类似工具目前还不是一个选项,所有东西都必须在一个webapp中工作。数据库是MSSQL。我试图做的是利用Lucene查询解析器并从中构建Hibernate标准。尽管我最初的印象是这不会太难,但我不知道如何为复杂的查询构建条件
下面是我创建的一个快速测试,用于使用Lucene(4.7.2)解析查询字符串
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_47);
QueryParser luceneParser = new QueryParser(Version.LUCENE_47, "", analyzer);
String queryString = "(name:\"Luke Skywalker\" AND father:unknown OR fname:Luke) or (name:yoda)";
Query luceneQuery = luceneParser.parse(queryString);
public class QueryInterpreter {
public void parse(Query query) {
if (query instanceof TermQuery) {
termQuery((TermQuery) query);
} else if (query instanceof BooleanQuery) {
booleanQuery((BooleanQuery) query);
} else if (query instanceof PhraseQuery) {
phraseQuery((PhraseQuery) query);
} else {
throw new IllegalArgumentException("");
}
}
public void booleanQuery(BooleanQuery query) {
for (BooleanClause clause : query.getClauses()) {
parse(clause.getQuery());
}
}
public void phraseQuery(PhraseQuery query) {
StringBuilder sb = new StringBuilder();
for (Term term : query.getTerms()) {
sb.append(term.text());
sb.append(" ");
}
}
public void termQuery(TermQuery query) {
Term term = query.getTerm();
}
}
Lucene first thing将搜索字符串转换为(+name:\"Luke Skywalker\" +father:unknown fname:Luke) name:yoda
。基本上,然后它通过为每个术语设置isRequired()来迭代术语。Hibernate的工作方式不同——您创建一个criteria对象并不断添加带有成对值的Criterian。我不知道如何把它们转换成另一个。我想我需要的是一个通用的连接对象来附加标准
# 1 楼答案
最后,我将在这里分享我的解决方案,以防有人面临同样的问题
正确方向的第一步是认识到
QueryParser
不能很好地处理布尔逻辑。例如(+name:\"Luke Skywalker\" +father:unknown fname:Luke) name:yoda
是与(name:\"Luke Skywalker\" AND father:unknown OR fname:Luke) or (name:yoda)
不同的搜索。我不知道为什么QueryParser甚至接受布尔逻辑,这很容易混淆解决方法是使用
PrecedenceQueryParser
然后从中创建一个Hibernate标准。显然,您不能在关系数据库中支持全方位的Lucene搜索功能,但这从来都不是必需的
希望有人会觉得这个有用