基于ElasticsearchRestTemplate的自定义高亮搜索

ElasticsearchRestTemplate是spring-data-elasticsearch项目中的一个类,和其他spring项目中的template类似。

在新版的spring-data-elasticsearch中,ElasticsearchRestTemplate代替了原来的ElasticsearchTemplate。原因是ElasticsearchTemplate基于TransportClientTransportClient即将在8.x以后的版本中移除。ElasticsearchRestTemplate基于RestHighLevelClient,如果不手动配置RestHighLevelClientbean,ElasticsearchRestTemplate将使用org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientConfigurations默认配置的RestHighLevelClientbaen,此时es服务器应当使用默认9200端口。

@Data
@Document(indexName = "qas2")
public class EsDocument {
    @Id
    private String id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title; //标题

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String keyWord; //关键字

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String content; //解答内容

    @Field(type = FieldType.Keyword)
    private String typeId; //类型id
}
@Service
public class EsService {
    @Autowired
    ElasticsearchRestTemplate template;
    @Autowired
    ObjectMapper objectMapper;

    public SearchResult search(String text, String typeId, int pageNum, int pageSize) {
        QueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(text);
        HighlightBuilder highlightBuilder = new HighlightBuilder()
                //.fragmentSize(8)
                .field("title").field("keyWord").field("content");
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder()
                .must(queryStringQueryBuilder);
        //根据类型
        if (!StringUtils.isEmpty(typeId)) {
            TermQueryBuilder termQuery = QueryBuilders.termQuery("typeId", typeId);
            boolQueryBuilder.must(termQuery);
        }
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withPageable(PageRequest.of(pageNum, pageSize))
                .build();

        SearchResult searchResult = new SearchResult();
        AggregatedPage<EsDocument> aggregatedPage =
                template.queryForPage(searchQuery, EsDocument.class, new SearchResultMapper() {
                    @Override
                    public <EsDoument> AggregatedPage<EsDoument> mapResults(SearchResponse response, Class<EsDoument> clazz, Pageable pageable) {
                        long total = response.getHits().totalHits;
                        searchResult.setTotal(total);
                        SearchHit[] hits = response.getHits().getHits();
                        LinkedList<EsDocument> list = new LinkedList<>();
                        for (SearchHit hit : hits) {
                            String source = hit.getSourceAsString();
                            EsDocument document = null;
                            try {
                                document = objectMapper.readValue(source, EsDocument.class);
                            } catch (Exception e) {
                                //ignore
                            }
                            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                            for (Map.Entry<String, HighlightField> entry : highlightFields.entrySet()) {
                                HighlightField field = entry.getValue();
                                try {
                                  //org.apache.commons.beanutils.PropertyUtils
                                    PropertyUtils.setProperty(document, field.getName(), highlightFieldToString(field));
                                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                                    //
                                }
                            }
                            list.add(document);
                        }
                        return new AggregatedPageImpl(list);
                    }

                    @Override
                    public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
                        return null;
                    }
                });
        List<EsDocument> list = aggregatedPage.getContent();
        searchResult.setData(list);
        return searchResult;
    }

    private String highlightFieldToString(HighlightField field) {
        Text[] texts = field.getFragments();
        StringBuilder sb = new StringBuilder();
        for (Text text : texts) {
            sb.append(text.string());
        }
        return subStr(sb.toString());
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容