Skip to content

Hibernate Search学习

文档参考: https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#mapper-orm-mapping-projection

如何使用 hibernate Search 进行导出的时候 search after 的操作

项目中使用的版本是: hibernate-search 7.0.0.Final 的版本

搜索模块: https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#query-sorting

在关联的 org.hibernate.search.engine.search.query.SearchQuery 以及 SearchFetchable 类下,没有看到 searchAfter 方法,只看到 scroll 方法

可能是 Hibernate Search 7.0 处于有限支持状态

这里转换为使用 原生的 ES 特性(项目使用的ES是 8 以上的版本)

了解一下 scroll 方法: https://blog.csdn.net/zx711166/article/details/82426387 (滚动查询,建议使用 search_after, search_after 是 ES5.0 及之后版本提供的新特性)

ES 原生的写法 是有 searchAfter 的直接调用方法的

这里是使用 hibernate search 的部分内容, 并且加入部分 json 的拼写操作

参考: https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search-dsl-query-elasticsearch-json

这种写法能够直接更改 body 的内容

最后的更新版本代码

default Page<SalesOrderProduct> findSalesOrderProductPaginatedByCriteriaForExport(FindSalesOrderProductPaginatedRequest request, PageRequest pageRequest) {  
  
    int maxQuantity = 10000;  
  
    if (pageRequest.getOffset() + pageRequest.getPageSize() > maxQuantity) {  
        throw new GenericException(GenericException.Code.SEARCH_RANGE_TOO_LARGE);  
    }  
  
    SearchMapping searchMapping = App.getBean(SearchMapping.class);  
  
    try (SearchSession session = searchMapping.createSession()) {  
        int offset = (request.getSearchAfterValues() != null  
            && request.getSearchAfterValues().getId() != null  
            && request.getSearchAfterValues().getUpdatedAtTimestamp() != null)  
            ? 0  
            : (int) pageRequest.getOffset();  
  
        SearchResult<SalesOrderProductEsDTO> searchResult = session.search(SalesOrderProductEsMapper.class)  
            .extension(ElasticsearchExtension.get())  
            .select(f -> f.composite()  
                .from(f.field("docId", Long.class), f.field("updatedAt", LocalDateTime.class))  
                .asList(list -> new SalesOrderProductEsDTO((Long) list.get(0), (LocalDateTime) list.get(1))))  
            .where(predicateContributor(request))  
            .requestTransformer(context -> {  
                if (request.getSearchAfterValues() != null  
                    && request.getSearchAfterValues().getId() != null  
                    && request.getSearchAfterValues().getUpdatedAtTimestamp() != null) {  
                    JsonArray searchAfter = new JsonArray();  
                    SalesOrderProductEsDTO lastResult = request.getSearchAfterValues();  
                    searchAfter.add(lastResult.getUpdatedAtTimestamp());  
                    searchAfter.add(lastResult.getId().toString());  
                    context.body().add("search_after", searchAfter);  
                }  
            })  
            .sort(sortContributor(pageRequest))  
            .fetch(offset, pageRequest.getPageSize());  
  
        List<SalesOrderProductEsDTO> hits = searchResult.hits();  
        if (hits != null && !hits.isEmpty()) {  
            request.setSearchAfterValues(hits.get(hits.size() - 1));  
        }  
        List<Long> ids = searchResult.hits().stream().map(SalesOrderProductEsDTO::getId).collect(Collectors.toList());  
        return new PageImpl<>(findSortedByIdIn(ids), pageRequest, searchResult.total().hitCount());  
    }  
}