【问题标题】:Build Lucene Query for multiple fields为多个字段构建 Lucene 查询
【发布时间】:2019-03-13 22:04:21
【问题描述】:

我有一个带有搜索功能的 Spring MVC 应用程序。

流程:UI > 控制器 > BL > 数据 > 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"

【问题讨论】:

  • new WildcardQuery(new Term("fieldName", "wildcardSearchstring")).toString()
  • 我确实喜欢这个 - 查询 q = new WildcardQuery(new Term("nm","helloworld"));结果是 nm:helloworld。我需要它是 nm:hello\\world
  • 对组合(布尔运算符)查询有什么建议吗?
  • 您可以有一个 BooleanQuery,它使用布尔查询添加接受多个通配符查询。

标签: java lucene


【解决方案1】:

可以像这样使用布尔查询构建器,例如:

new BooleanQuery.Builder().add(query1, BooleanClause.OCCUR.MUST)
                              .add(query2, BooleanClause.OCCUR.MUST_NOT)
                              .build();

如果您希望对字段和搜索字符串进行复杂的聚合 - 您可以编写类似 -

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);
        }
    }
}

【讨论】:

  • 我喜欢您的回答,但是您通过的条款在我的情况下并非如此。如果用户传递了类似:comm*y 大学 - 那么它应该返回所有包含“comm”之间的任何内容和一个单词中的“y”,然后是“college”的记录。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-12
  • 1970-01-01
相关资源
最近更新 更多