elasticsearch通用工具类

文章详细描述了如何在SpringBoot项目中使用Elasticsearch7.11.1版本,通过Java反射技术实现索引管理、搜索查询(包括普通、多字段高亮和单字段高亮)、以及根据查询结果动态更新对象属性的过程。
摘要由CSDN通过智能技术生成

环境

jdk:13

es:     7.11.1

springboot:2.6.13

依赖包


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

注意

利用反射实现了高亮替换,如果是内部类的字段,将该字段提出来设为外部类的字段

Esutil.java

@Slf4j
@Component
public class EsUtil {
    @Resource
    private ElasticsearchRestTemplate restTemplate;


    /**
     * 创建索引,并设置映射。
     * 需要通过两次访问实现,1、创建索引;2、设置映射。
     */
    public Boolean initIndex(Class clazz){

        // 创建索引和映射,根据类型上的Document注解创建
        return restTemplate.indexOps(clazz).create()||restTemplate.indexOps(clazz).putMapping();

    }
    /**
     *删除索引
     */

    public Boolean deleteIndex(Class clazz){
        //创建索引,系统初始化会自动创建索引
       return restTemplate.indexOps(clazz).delete();

    }


    /**
     *检查索引是否存在
     */
    public Boolean isIndex(Class clazz){
        return restTemplate.indexOps(clazz).exists();
    }
    /**
     *普通查询
     * @param startTime 开始时间
     * @param endTime    结束时间
     * @param timestamp  时间字段
     * @param field 查询字段
     * @param keywords 查询关键字
     * @param from 第几页(0)
     * @param size 一页有几条数据
     * @param clazz 数据格式化的实体类对象
     */
    public     SearchHits<?> search(
            Date startTime,
            Date endTime,
            String timestamp,
            String field,
            String keywords,
            Integer from,
            Integer size,
            Class clazz
    ){

        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();

        if(startTime!=null && endTime!=null && timestamp!=null){
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery(timestamp)
                    .gte(startTime)
                    .lte(endTime);
            searchQueryBuilder.withFilter(rangeQuery);
        }
        //指定查询条件
        if(keywords!=null){
            searchQueryBuilder.withQuery(QueryBuilders.matchQuery(field,keywords));
        }else {
            searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
        }
        //指定排序
        searchQueryBuilder.withSorts(SortBuilders.fieldSort("id").order(SortOrder.DESC));
        //分页
        searchQueryBuilder.withPageable(PageRequest.of(from,size));
        //构建查询对象
        NativeSearchQuery searchQuery = searchQueryBuilder.build();
        //执行查询
        SearchHits<?> searchHits = restTemplate.search(searchQuery,clazz);

        return searchHits;

    }
    /**
     *多字段高亮查询
     *  @param startTime 开始时间
     *  @param endTime    结束时间
     *  @param timestamp  时间字段
     * @param highlightFields 查询字段(高亮字段)
     * @param keywords 查询关键字
     * @param from 第几页(0)
     * @param size 一页有几条数据
     * @param clazz 数据格式化的实体类对象
     *
     */

    public SearchHits<?> searchMulti(
            Date startTime,
            Date endTime,
            String timestamp,
            String keywords,
            Integer from,
            Integer size,
            Class clazz,
            String... highlightFields
    ){
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        //指定查询条件
        if(startTime!=null && endTime!=null && timestamp!=null){
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery(timestamp)
                    .gte(startTime)
                    .lte(endTime);
            searchQueryBuilder.withFilter(rangeQuery);
        }
        if(keywords!=null){
            searchQueryBuilder.withQuery(QueryBuilders.multiMatchQuery(keywords,highlightFields));
        } else {
            searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
        }

        searchQueryBuilder.withSorts(SortBuilders.fieldSort("id").order(SortOrder.DESC));
        //分页
        searchQueryBuilder.withPageable(PageRequest.of(from,size));
        //构建查询对象
        NativeSearchQuery searchQuery = searchQueryBuilder.build();
        //执行查询
        SearchHits<?> searchHits = restTemplate.search(searchQuery,clazz);

        return searchHits;
    }
    /**
     *单一字段高亮查询
     * @param startTime 开始时间
     * @param endTime    结束时间
     * @param timestamp  时间字段
     * @param field 查询字段(高亮字段)
     * @param keywords 查询关键字
     * @param from 第几页(0)
     * @param size 一页有几条数据
     * @param clazz 数据格式化的实体类对象
     *
     */

    public SearchHits<?> searchWithHighlight(
            Date startTime,
            Date endTime,
            String timestamp,
            String field,
            String keywords,
            Integer from,
            Integer size,
            Class clazz

    ){
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        //指定查询条件
        if(startTime!=null && endTime!=null){
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery(timestamp)
                    .gte(startTime)
                    .lte(endTime);
            searchQueryBuilder.withFilter(rangeQuery);
        }
        if(keywords!=null){
            searchQueryBuilder.withQuery(QueryBuilders.matchQuery(field,keywords));
        } else {
                searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
        }

        //指定排序,如果不指定默认按着得分进行排序
        searchQueryBuilder.withSorts(SortBuilders.fieldSort("id").order(SortOrder.DESC));

        //分页
        searchQueryBuilder.withPageable(PageRequest.of(from,size));

        //指定高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //指定高亮的字段
        highlightBuilder.field(field);
        //指定高亮的标
        highlightBuilder.preTags("<span style='color:red;'>").postTags("</span>");
        searchQueryBuilder.withHighlightBuilder(highlightBuilder);
        //构建查询对象
        NativeSearchQuery searchQuery = searchQueryBuilder.build();
        //执行查询
        SearchHits<?> searchHits = restTemplate.search(searchQuery,clazz);

        for (SearchHit hit : searchHits.getSearchHits()){

            if(hit.getHighlightFields().isEmpty()){
                return searchHits;
            }
            //利用反射,调用所查询字段的set方法,将高亮字段里的值赋给原来的字段
            hit.getHighlightFields().forEach((key,value)->
            {
                try {

                             Field resField =hit.getContent().getClass().getDeclaredField((String)key);
                            resField.setAccessible(true);
                            setValue(hit.getContent(),
                           hit.getContent().getClass(),
                           (String)key,
                           resField.getType(),
                           value.toString().substring(1,value.toString().length()-1));

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });

        }

        return searchHits;


    }
    /**
     *多字段高亮查询
     *  @param startTime 开始时间
     *  @param endTime    结束时间
     *  @param timestamp  时间字段
     * @param highlightFields 查询字段(高亮字段)
     * @param keywords 查询关键字
     * @param from 第几页(0)
     * @param size 一页有几条数据
     * @param clazz 数据格式化的实体类对象
     *
     */

    public SearchHits<?> searchWithHighlightMulti(
            Date startTime,
            Date endTime,
            String timestamp,
            String keywords,
            Integer from,
            Integer size,
            Class clazz,
           String... highlightFields
    ){
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        //指定查询条件
        if(startTime!=null && endTime!=null && timestamp!=null){
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery(timestamp)
                    .gte(startTime)
                    .lte(endTime);
            searchQueryBuilder.withFilter(rangeQuery);
        }
        if(keywords!=null){
            searchQueryBuilder.withQuery(QueryBuilders.multiMatchQuery(keywords,highlightFields));
        } else {
            searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
        }

        searchQueryBuilder.withSorts(SortBuilders.fieldSort("id").order(SortOrder.DESC));
        //分页
        searchQueryBuilder.withPageable(PageRequest.of(from,size));

        //指定高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //指定高亮的字段
        for(String field:highlightFields){
            highlightBuilder.field(field);
        }

        //指定高亮的标签
        highlightBuilder.preTags("<span style='color:red;'>").postTags("</span>");

        searchQueryBuilder.withHighlightBuilder(highlightBuilder);

        //构建查询对象
        NativeSearchQuery searchQuery = searchQueryBuilder.build();
        //执行查询
        SearchHits<?> searchHits = restTemplate.search(searchQuery,clazz);

        for (SearchHit hit : searchHits.getSearchHits()){

            if(hit.getHighlightFields().isEmpty()){
                return searchHits;
            }
            //利用反射,调用所查询字段的set方法,将高亮字段里的值赋给原来的字段
            hit.getHighlightFields().forEach((key,value)->
            {
                try {

                    Field resField =hit.getContent().getClass().getDeclaredField((String)key);
                    resField.setAccessible(true);
                    setValue(hit.getContent(),
                            hit.getContent().getClass(),
                            (String)key,
                            resField.getType(),
                            value.toString().substring(1,value.toString().length()-1));

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });

        }
        return searchHits;
    }

    /**
     * 根据属性,拿到set方法,并把值set到对象中
     * @param obj 对象
     * @param clazz 对象的class
     * @param filedName 需要设置值得属性
     * @param typeClass
     * @param value
     */
    private void setValue(Object obj,Class<?> clazz,String filedName,Class<?> typeClass,Object value){
        filedName = removeLine(filedName);

        String methodName = "set" + filedName.substring(0,1).toUpperCase()+filedName.substring(1);
        try{
            Method method =  clazz.getDeclaredMethod(methodName, new Class[]{typeClass});
            method.invoke(obj, new Object[]{getClassTypeValue(typeClass, value)});
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    /**
     * 处理字符串  如:  abc_dex ---> abcDex
     * @param str
     * @return
     */
    private  String removeLine(String str){
        if(null != str && str.contains("_")){
            int i = str.indexOf("_");
            char ch = str.charAt(i+1);
            char newCh = (ch+"").substring(0, 1).toUpperCase().toCharArray()[0];
            String newStr = str.replace(str.charAt(i+1), newCh);
            String newStr2 = newStr.replace("_", "");
            return newStr2;
        }
        return str;
    }
    /**
     * 通过class类型获取获取对应类型的值
     * @param typeClass class类型
     * @param value 值
     * @return Object
     */
    private Object getClassTypeValue(Class<?> typeClass, Object value){
        if(typeClass == int.class  || value instanceof Integer){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == short.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == byte.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == double.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == long.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == String.class){
            if(null == value){
                return "";
            }
            return value;
        }else if(typeClass == boolean.class){
            if(null == value){
                return true;
            }
            return value;
        }else if(typeClass == BigDecimal.class){
            if(null == value){
                return new BigDecimal(0);
            }
            return new BigDecimal(value+"");
        }else {
            return typeClass.cast(value);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值