java - 为多个字段构建 Lucene 查询
问题描述
我有一个具有搜索功能的 Spring MVC 应用程序。
流程:UI > CONTROLLER > BL > DATA > SOLR
允许用户使用多个字段搜索某些内容,例如按名称或部门搜索。业务层需要有一个 Lucene Query Builder,它接受字符串并为 SOLR 构建适当的 Lucene 查询。
我的控制器:
@GetMapping(params = "name")
public Page<User> findUserByName(@RequestParam("name") final String name) {
return userService.findUserByName(name);
}
@GetMapping(params = "department")
public Page<User> findUserByDepartment(@RequestParam final String department) {
return userService.findUserByFulltext(department);
}
虚拟查询生成器
public String searchByNameQuery(final String name) {
return "nm:" + name;
}
public String searchByDepartmentQuery(final String department) {
return "dpt:" + department;
}
现在这个虚拟查询构建器不支持通配符或任何其他变体。我正在浏览 Apache Lucene Query API(也将 lucene core-7.7.1 添加到项目中)和一堆教授如何使用不同类型的查询实现(TermQuery、PhraseQuery、BooleanQuery 等)的文章,但它没有完全有道理。最后,我仍在手动构建查询。
有人可以通过展示我如何拥有一个正确的 Lucene 查询生成器类来帮忙吗?
我需要使用精确的短语和通配符为这些类型的文本生成查询
(exact)Search by name: Ohio State University
Search by name: *State
Search by name: Ohio*University
Search by name: Ohio State*
Search by Department:Computer Science Dept
Search by Department: *Science
组合查询:
nm:"Ohio State University" AND dpt:"Computer Science"
解决方案
A boolean query builder can be used like this for eg:
new BooleanQuery.Builder().add(query1, BooleanClause.OCCUR.MUST)
.add(query2, BooleanClause.OCCUR.MUST_NOT)
.build();
And if you would prefer to have complex aggregation , for the field and search strings - you may write something like -
public class CustomBooleanQueryBuilder {
public Map<BooleanClause.Occur, List<Query>> getClauseQueryMap() {
return clauseQueryMap;
}
private final Map<BooleanClause.Occur, List<Query>> clauseQueryMap = new HashMap();
public static void main(String args[]) throws ParseException {
CustomBooleanQueryBuilder queryBuilder = new CustomBooleanQueryBuilder();
final Query regExpQuery = new RegexpQuery(new Term("nm", "Hello\\sWorld"));
queryBuilder.addUpdateQueryMap(regExpQuery, BooleanClause.Occur.MUST);
final Query wildcardQuery = new WildcardQuery(new Term("nm", "Hello?World"));
queryBuilder.addUpdateQueryMap(wildcardQuery, BooleanClause.Occur.MUST_NOT);
System.out.println(queryBuilder.aggregateQueryBoolean(queryBuilder.clauseQueryMap));
}
private String aggregateQueryBoolean(final Map<BooleanClause.Occur, List<Query>> clauseQueryMap) {
final BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
clauseQueryMap.forEach((booleanClause, queryList) -> queryList.forEach((query) -> booleanQueryBuilder.add(query, booleanClause)));
return booleanQueryBuilder.build().toString();
}
private void addUpdateQueryMap(final Query query, final BooleanClause.Occur booleanOccur) {
if (clauseQueryMap.containsKey(booleanOccur)) {
clauseQueryMap.get(booleanOccur).add(query);
} else {
final List<Query> queryList = new ArrayList();
queryList.add(query);
clauseQueryMap.put(booleanOccur, queryList);
}
}
}
推荐阅读
- hash - Argon2 的最大输入和输出长度
- windows - 使用 delphi 应用程序在 Windows 中接收推送通知?
- javascript - 承诺中的变量
- vb.net - 查找字符串并将其移至文档顶部
- django - Django Push_notification 的裸设备无法导入
- java - 避免在 Jbehave 步骤中使用 switch 语句
- javascript - 在 Highstock/Highcharts 中设置 rangeSelector 容器的背景颜色
- c++ - 停止在线程中运行的类方法
- python - 如何通过唯一键拆分数组?
- excel - 如何根据单元格值重命名工作表