Elasticsearch 多字段高亮分页查询 返回泛型List集合

时间:2021-09-13
本文章向大家介绍Elasticsearch 多字段高亮分页查询 返回泛型List集合,主要包括Elasticsearch 多字段高亮分页查询 返回泛型List集合使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
/*
 * @Copyright (c) 2021. 于吉利 All Rights Reserved
 * @Author: 于吉利
 * @Function:
 * @Date: 2021/9/13 下午2:11
 * @version:1.0
 * @Changes:
 * @Description:
 *
 */

package com.huajun.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huajun.search.entity.Product;
import com.huajun.search.service.ISmartQuery;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.elasticsearch.common.text.Text;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class SmartQueryImpl implements ISmartQuery {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private ObjectMapper objectMapper;


    @Override
    public List<Product> searcher(String keyWords, String indexName, Integer pageNum, Integer pageSize) {

        List<Product> productInfos = new ArrayList<Product>();
        SearchRequest searchRequest;
        if (indexName == "all") {
             searchRequest = new SearchRequest(indexName);
        } else {
             searchRequest = new SearchRequest();////穿件SeachRequest,Without arguments this runs against all indices.
        }
        SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();
        //分页开始
        //searchSourceBuilder.from(0).size(10);
        //init
        if (pageSize == null) {
            pageSize = 10;
        }
        if (pageNum == null) {
            pageNum = 1;
        }
        Integer from = (pageNum - 1) * pageSize;
        if (from <= 0) {
            from = 0;
        }
        searchSourceBuilder.from(from);
        searchSourceBuilder.size(pageSize);
        //设置一个可选的超时时间,用于可控制搜索允许的时间
        searchSourceBuilder.timeout(new TimeValue(1200, TimeUnit.SECONDS));
        //将数据按date排序
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("createdate").order(SortOrder.DESC);
        searchSourceBuilder.sort(sortBuilder);

        //创建queryBuilder, 从es字段:name,content多字段查询
        QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(keyWords, "name", "content").operator(Operator.OR);
        searchSourceBuilder.query(queryBuilder);

        //设置需要高亮的es字段
        String preTags = "<span style='color:#29bf9d'>";
        String postTags = "</span>";
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags(preTags);//设置前缀
        highlightBuilder.postTags(postTags);//设置后缀
        highlightBuilder.field("name");//设置高亮字段
        highlightBuilder.field("content");//设置高亮字段
        //设置多个高亮显示为false,根据需求也可以设置为true
        highlightBuilder.requireFieldMatch(false);
        //下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等
        highlightBuilder.fragmentSize(800000); //最大高亮分片数
        highlightBuilder.numOfFragments(0); //从第一个分片获取高亮片段
        searchSourceBuilder.highlighter(highlightBuilder);//设置高亮信息
        searchRequest.source(searchSourceBuilder);

        try {
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            //return toProductList(response.getHits().getHits()).stream().findFirst().orElse(null);
            return toProductList(response.getHits().getHits());
            //

        } catch (Exception e) {
            e.printStackTrace();
        }


        return null;
    }


    private List<Product> toProductList(SearchHit[] searchHits) throws Exception {
        List<Product> productList = new ArrayList<>();
        for (SearchHit searchHit : searchHits) {
            Product Productinfo = JSON.parseObject(searchHit.getSourceAsString(), Product.class);
            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
            if (!highlightFields.isEmpty()) {
                HighlightField name = highlightFields.get("name");
                if (name != null) {
                    Productinfo.setName(Arrays.stream(name.getFragments()).map(Text::string).collect(Collectors.joining("\n")));
                }
                HighlightField content = highlightFields.get("content");
                if (content != null) {
                    Productinfo.setContent(Arrays.stream(content.getFragments()).map(Text::string).collect(Collectors.joining("\n")));
                }
            }
            productList.add(Productinfo);
            //productList.add(searchHit.getSourceAsMap());
            //productList.add(objectMapper.readValue(searchHit.getSourceAsString(), Product.class));
            //productList.add(objectMapper.readValue(searchHit.getSourceAsString(), Product.class));
        }
        return productList;
    }


}

原文地址:https://www.cnblogs.com/Jeely/p/15263274.html