Построить Lucene Query для нескольких полей - PullRequest
0 голосов
/ 14 марта 2019

У меня есть весеннее приложение MVC с возможностями поиска.

Поток: UI> КОНТРОЛЛЕР> BL> ДАННЫЕ> SOLR

Пользователи могут искать что-то, используя несколько полей, например, поиск по имени или отделу. Бизнес-уровень должен иметь построитель запросов Lucene, который принимает строку и создает правильный запрос Lucene для SOLR.

Мой контроллер:

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

Dummy Query Builder

public String searchByNameQuery(final String name) {
    return "nm:" + name;
}
public String searchByDepartmentQuery(final String department) {
    return "dpt:" + department;
}

Теперь этот фиктивный построитель запросов не поддерживает подстановочные знаки или любые другие варианты. Я рассматриваю API запросов Apache Lucene (также добавлен lucene core-7.7.1 в проект) и кучу статей, в которых рассказывается, как использовать различные типы реализаций запросов (TermQuery, PhraseQuery, BooleanQuery и т. Д.), Но это не так. имеет смысл вообще. В конце концов, я все еще вручную строю запросы.

Может ли кто-нибудь помочь, показывая, как у меня может быть правильный класс Lucene Query Builder?

Мне нужно сгенерировать запросы для этих типов текстов с точной фразой и подстановочными знаками

(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"

1 Ответ

0 голосов
/ 15 марта 2019

Конструктор булевых запросов можно использовать, например, для:

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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...