ElasticSearch结合springboot常规用法总结

3 篇文章 0 订阅
1 篇文章 0 订阅

ES结合springboot的常规用法总结:
引jar、配置工具类,客户端等忽略。

建议先熟悉利用kibana查询ES的语句,那样写起来更容易,也方便问题排查。

一、es查询必须的几个对象:

1. 普通查询的条件容器:BoolQueryBuilder 多条件查询容器 

BoolQueryBuilder builder=QueryBuilders.boolQuery();    普通的QueryBuilders查询的boolQuery()方法,变成多条件查询
        比如时间条件:boolQueryBuilder.filter(QueryBuilders.rangeQuery(EsConstant.ES_INSERT_TIME).gte(twoHoursInfo.get(0)).lte(twoHoursInfo.get(1)));

2. 分组查询的条件容器:AggregationBuilder 

 AggregationBuilder field = AggregationBuilders.terms(AGG_NAME).field(Constant.ES_TITLE);

3. 普通的分组查询:

注意如果要分组的字段是text类型,需要转成key类型才能分组,直接字段.key就行。在分组后直接.subAggregation(。。。。。) 可以添加子分组。

查询条件总容器:SearchSourceBuilder 

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        比如:searchSourceBuilder.query(boolQueryBuilder).aggregation(termsAggregationBuilder);

4. 创建查询容器:SearchRequest 

  方式一:SearchRequest searchRequest = new SearchRequest(INDEX_NAME).source(searchSourceBuilder);
    方式二:SearchRequest searchRequest = new SearchRequest().indices(INDEX_NAME).source(searchSourceBuilder);


5. 放入提前配置好的客户端:

        SearchResponse是返回值的容器

SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

二、解析容器分为两种:

普通条件结果解析:
        方式一:
        TrendingResponse trendingResponse = new TrendingResponse();  //要装载结果的实体类
        SearchHit[] hits = searchResponse.getHits().getHits();
        int length = hits.length;
        if(length>0){
            Map<String, Object> sourceAsMap = hits[0].getSourceAsMap();
            trendingResponse = modelMapper.map(sourceAsMap, TrendingResponse.class);
        }
        方式二:
        SearchHit[] hits = searchResponse.getHits().getHits();
        if(hits.length>0){
            Arrays.asList(hits).stream().forEach(hit -> {
                TrendingResponse trendingResponse = new TrendingResponse();  //要装载结果的实体类
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                trendingResponse = modelMapper.map(sourceAsMap, TrendingResponse.class);
                trendingResponseList.add(trendingResponse);
             });
        }


    
    分组条件结果解析:

 方式一:
        ParsedStringTerms aggregation = searchResponse1.getAggregations().get(AGG_NAME);
        List<? extends Terms.Bucket> buckets = aggregation.getBuckets();
        for(Terms.Bucket bucket:buckets){
            TrendingResponse trendingResponse = new TrendingResponse();  //要装载结果的实体类
            trendingResponse.setPlatform(bucket.getKeyAsString());       //封装的解析方法
            trendingResponseList.add(trendingResponse);
        }    
        
        方式二:
        ParsedTerms terms = response.getAggregations().get("termsAgg")
        return  terms.getBuckets().stream().map(it -> new Target(it.getKeyAsString(),it.getDocCount(),
        dateHistogramAgg(it.getAggregations(), "yyyy-MM-dd HH:mm"))).collect(Collectors.toList());  注意:多利用类的有参构造:直接转换成需要的类对象

这是查询数据内容的方式,每次只能查出10000条,这是es默认的。如果想查出更多,可以采用滚动查询,这个以后再总结

三、日常用法:    

1. 只是查询总数的写法:

 logger.info("getAllCount 统计总数");
        long value = 0;
        List<Long> twoHoursInfo = new ArrayList<>();
        twoHoursInfo.add(System.currentTimeMillis()-86400000);
        twoHoursInfo.add(System.currentTimeMillis());
        String[] indexs = new String[]{EsConstant.ES_INDEX_BASEDATA,EsConstant.ES_INDEX_BOARD,EsConstant.ES_INDEX_APPS,EsConstant.ES_INDEX_ACCOUNT};
        CountRequest countRequest = new CountRequest(indexs,QueryBuilders.rangeQuery(EsConstant.ES_INSERT_TIME).gte(twoHoursInfo.get(0)).lte(twoHoursInfo.get(1)));
        try {
            CountResponse count = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);
            value = count.getCount();
        } catch (IOException e) {
            logger.error("插入基础数据getMsgTypeData 报错:{}",e);
        }
        return value;


        
2.利用es的分词进行,匹配实现模糊查询:

 boolQueryBuilder.filter(QueryBuilders.wildcardQuery(EsConstant.ES_PRODUCT_NAME,"*"+productName+"*")); 
    注意:ElasticSearchTemplate加中文筛选后无结果的解决办法:title.keyword


    
3. es实现简单的分页查询:(不推荐)

 new SearchSourceBuilder().query(boolQueryBuilder).from(pageNum*pageSize).size(pageSize);

4. 常规查询工具类

@Component
public class BaseSearchSourceBuilder extends BaseAggregationBuilder {

    @Resource
    private DetectionConfigRepository detectionConfigRepository;

    public SearchSourceBuilder searchSourceBuilder(HeartbeatDetectionListVO condition){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        Long startTime = null;
        Long endTime =  null;
        if(Objects.nonNull(condition.getStartTime())){
            startTime = condition.getStartTime().getTime();
            endTime = condition.getEndTime().getTime();
        }

        if (Objects.nonNull(startTime) && Objects.nonNull(endTime)){
                                        
boolQueryBuilder.filter(QueryBuilders.rangeQuery(EsConstant.ES_DETECTION_TIME_STMP).gte(startTime).lte(endTime));
        }
        String keyword = condition.getStatus();
        if (StringUtils.isNotBlank(keyword)){
            long state = 0;
            if(keyword.equals("ONLINE")){
                state=1;
            }else {
                state=2;
            }
            //TODO 与或非
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(EsConstant.ES_RESULT_STATUS, state);
            boolQueryBuilder.filter(termQueryBuilder);
        }
        String productCode = condition.getProductCode();
        if (StringUtils.isNotBlank(productCode)){
            boolQueryBuilder.filter(QueryBuilders.termQuery(EsConstant.ES_PRODUCT_CODE,productCode));
        }
        String resultCode = condition.getResultCode();
        if (StringUtils.isNotBlank(resultCode)){
            boolQueryBuilder.filter(QueryBuilders.termQuery(EsConstant.ES_RESULT_CODE,resultCode));
        }
        List<String> messageList = condition.getMessageList();
        if(CollectionUtils.isNotEmpty(messageList)){
            boolQueryBuilder.filter(QueryBuilders.termsQuery(EsConstant.ES_RESULT_CODE,messageList));
        }
        String productName = condition.getProductName();
        if (StringUtils.isNotBlank(productName)){
            boolQueryBuilder.filter(QueryBuilders.wildcardQuery(EsConstant.ES_PRODUCT_NAME,"*"+productName+"*"));
        }
        String message = condition.getMessage();
//        if (StringUtils.isNotBlank(message)){
//            boolQueryBuilder.filter(QueryBuilders.queryStringQuery(message).defaultField(EsConstant.ES_RESULT_REASON));
//        }
        if (StringUtils.isNotBlank(message)){
            boolQueryBuilder.filter(QueryBuilders.termQuery(EsConstant.ES_RESULT_CODE,message));
        }
        Integer pageSize = condition.getSize();
        if (Objects.isNull(pageSize)){
            pageSize = 0;
        }
        Integer pageNum = condition.getNumber();
        if (Objects.isNull(pageNum)){
            pageNum = 0;
        }
        return new SearchSourceBuilder().query(boolQueryBuilder).from(pageNum*pageSize).size(pageSize);
    }
}

5. 聚合查询工具类:

public class BaseAggregationBuilder {

    /**
     * TopHitsAggregation sort <>pt asc</>
     * @param topHitsName
     * @return
     */
    public TopHitsAggregationBuilder topHitsAggregationBuilder(String topHitsName, Integer size){
        return AggregationBuilders.topHits(topHitsName).sort(EsConstant.ES_DETECTION_TIME, SortOrder.DESC).size(size);
    }
    /**
     * TermsAggregation
     * @param termsAggName
     * @param fieldName
     * @param size
     * @return
     */
    public TermsAggregationBuilder termsAggregationBuilder(String termsAggName, String fieldName, Integer size){
        return AggregationBuilders.terms(termsAggName).field(fieldName).size(size).executionHint("map");
    }

    /**
     * AggregationBuilders
     * @param cardinalityAggName
     * @param fieldName
     * @param
     * @return
     */
    public CardinalityAggregationBuilder cardinalityAggregationBuilder(String cardinalityAggName, String fieldName){
        return AggregationBuilders.cardinality(cardinalityAggName).field(fieldName);
    }

    /**
     * DateHistogramAggregation
     * @param dateHistogramFieldName
     * @return
     */
    public DateHistogramAggregationBuilder dateHistogramAggregationBuilder(String dateHistogramName, String dateHistogramFieldName){
        return AggregationBuilders.dateHistogram(dateHistogramName).fixedInterval(new DateHistogramInterval("1d"))
                .field(dateHistogramFieldName);
    }

    /**
     * DateHistogramAggregation
     * @param dateHistogramFieldName
     * @return
     */
//    public DateHistogramAggregationBuilder dateHistogramAggregationFormatBuilder(String dateHistogramName, String dateHistogramFieldName,
//                                                                           DateHistogramInterval interval,Long startTime,Long endTime){
//        return AggregationBuilders.dateHistogram(dateHistogramName).fixedInterval(interval)
//                .field(dateHistogramFieldName).format("yyyy-MM-dd HH:mm").minDocCount(0).extendedBounds(new LongBounds(startTime,endTime)).timeZone(ZoneId.of("Asia/Shanghai"));
//    }

    /**
     * SumAggregation
     * @param sumAggName
     * @param fieldName
     * @return
     */
    public SumAggregationBuilder sumAggregationBuilder(String sumAggName,String fieldName){
        return AggregationBuilders.sum(sumAggName).field(fieldName);
    }

    /**
     * AvgAggregation
     * @param avgAggName
     * @param fieldName
     * @return
     */
    public AvgAggregationBuilder avgAggregationBuilder(String avgAggName, String fieldName){
        return AggregationBuilders.avg(avgAggName).field(fieldName);
    }

    /**
     * MaxAggregation
     * 最大值
     */
    public MaxAggregationBuilder maxAggregationBuilder(String maxAggName, String fieldName){
        return AggregationBuilders.max(maxAggName).field(fieldName);
    }

    /**
     * MinAggregation
     * 最小值
     */
    public MinAggregationBuilder minAggregationBuilder(String maxAggName, String fieldName){
        return AggregationBuilders.min(maxAggName).field(fieldName);
    }



}

6. 多查询并列查询:

        当需要多条件查询的时候,尽量一条语句全部查出来,这样性能好很多,类似sql语句的  

where (条件一 and 条件二 and 条件三) or  (条件四 and 条件五 and 条件六) or 。。。

public  List<Map<String, Object>> getImageInfoEs(List<SearchImageInfo> listSearchImageInfo){
        String[] indexs = new String[]{EsConstant.BASE_DATA,EsConstant.INDEX_APPS,EsConstant.INDEX_ACCOUNT,EsConstant.INDEX_ACCOUNT};
        SearchSourceBuilder searchSourceBuilder = searchSourceBuilder(listSearchImageInfo);
        SearchResponse search = esService.search(indexs, searchSourceBuilder);
        SearchHit[] hits = search.getHits().getHits();
        log.info("================从es查询的结果:hits.length : ==============={}",hits.length);
        Map<String, SearchImageInfo> searchImageInfoMap = new HashMap<>();
        listSearchImageInfo.stream().forEach(t->{
            String key = t.getMedia_id()+""+t.getMsg_id_s()+""+t.getMsg_type();
            searchImageInfoMap.put(key,t);
        });
        List<Map<String, Object>> listMap = new ArrayList<>();
        if(hits.length>0){
            Arrays.asList(hits).stream().forEach(hit -> {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String keylog = sourceAsMap.get(EsConstant.MEDIA_ID)+"------"+sourceAsMap.get(EsConstant.MSG_ID_S)+"-------"+sourceAsMap.get(EsConstant.MSG_TYPE);
                log.info("-------------------------从es查询的结果--------------------{}",keylog);
                sourceAsMap.put("_id",hit.getId());
                sourceAsMap.put("index",hit.getIndex());
                ......业务代码处理
                listMap.add(sourceAsMap);
            });
        }
        return listMap;
    }

    public SearchSourceBuilder searchSourceBuilder(List<SearchImageInfo> listSearchImageInfo){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        listSearchImageInfo.stream().forEach(t->{
            //通过should进行多条件拼接
                boolQueryBuilder.should(QueryBuilders.boolQuery().must(QueryBuilders.termQuery(EsConstant.MEDIA_ID,t.getMedia_id())).must(QueryBuilders.termQuery(EsConstant.MSG_ID_S,t.getMsg_id_s())).must(QueryBuilders.termQuery(EsConstant.MSG_TYPE,t.getMsg_type())));
        });
        return new SearchSourceBuilder().query(boolQueryBuilder).from(0).size(1000);
    }

7. 只根据数据的es  id查询,效率高

根据数据的id直接查询:

方式一:get方式不能用索引别名,但是效率高

		public GetResponse getOne(String index, String docId) {
        GetRequest getRequest = new GetRequest(index,docId);
        getRequest.preference(prefrence());
        GetResponse getResponse = null;
        try {
            getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("getOne fail,cause by {}", e.getCause());
        }
        return getResponse;
    }
	
方式二:这种方式可以,但是套的层比get方式多,效率略不如。

	//id可以是一个字符串类型的数组
	public SearchResponse getOneById(String index, String docId) {
        SearchRequest searchRequest = new SearchRequest(index);//指定索引
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.idsQuery().addIds(docId));
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = null;
        try {
            search = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("getOne fail,cause by {}", e.getCause());
        }
        return search;
    }

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Elasticsearch是一个开源的分布式全文搜索和分析引擎,而Spring BootJava开发的一种快速开发框架。将两者整合可以提供一个强大的搜索和分析功能的应用程序。 使用Spring Boot整合Elasticsearch的过程如下: 1. 首先,在pom.xml文件中添加ElasticsearchSpring Boot相关的依赖项。例如,添加spring-boot-starter-data-elasticsearch依赖来使用Spring Data Elasticsearch模块。 2. 在应用程序的配置文件中,配置Elasticsearch的连接参数,如主机地址、端口号等。可以使用Spring Boot的配置注解来简化配置过程。 3. 创建一个实体类,使用注解定义其映射到Elasticsearch索引的方式。可以使用@Document注解设置索引名称、类型等属性,使用@Field注解设置字段的映射方式。 4. 创建一个Elasticsearch的Repository接口,继承自Spring Data Elasticsearch提供的ElasticsearchRepository接口。可以使用该接口提供的方法来进行索引的增删改查操作。 5. 在需要使用Elasticsearch的业务逻辑中,注入创建的Repository接口实例,通过调用其方法来实现对索引的操作。例如,可以使用save方法保存实体对象到索引中,使用deleteById方法删除索引中的记录。 通过以上步骤,就可以实现ElasticsearchSpring Boot的整合。使用Spring Boot可以极大地简化了配置和开发的过程,而Elasticsearch提供了强大的全文搜索和分析功能,可以为应用程序提供高效的搜索和查询性能。整合后的应用程序可以方便地使用Elasticsearch进行数据索引和搜索操作。 ### 回答2: Elasticsearch是一个开源的搜索引擎,可以用于处理大量数据的搜索、分析和存储。Spring Boot是一个用于快速构建应用程序的框架,可以简化开发过程并提供各种强大功能。 将ElasticsearchSpring Boot整合可以实现在应用程序中使用Elasticsearch进行数据的索引、搜索和分析。下面是一个简单的步骤来实现这个整合: 1. 添加依赖:在Spring Boot项目的pom.xml文件中,添加Elasticsearch相关的依赖。例如,可以使用spring-boot-starter-data-elasticsearch依赖来集成Elasticsearch。 2. 配置连接:在Spring Boot的配置文件中,配置Elasticsearch连接的相关信息,如主机地址、端口号、用户名和密码等。 3. 创建实体类:根据需要,创建要在Elasticsearch中索引的实体类。实体类一般使用注解来标识其在Elasticsearch中的索引和字段的映射关系。 4. 创建Repository:使用Spring Data Elasticsearch提供的@Repository注解来创建Elasticsearch的Repository接口。这个接口可以继承ElasticsearchRepository,并提供一些自定义的查询方法。 5. 编写业务逻辑:在Service层编写业务逻辑,调用自定义的Repository接口方法来对Elasticsearch进行操作。 6. 启动应用程序:使用Spring Boot的注解@SpringBootApplication来启动应用程序,其中会自动加载Elasticsearch的配置和相关的依赖。 通过以上步骤,我们就成功地将Elasticsearch整合到了Spring Boot应用程序中。可以通过访问RESTful接口来对Elasticsearch进行索引、搜索和分析等操作。此外,Spring Boot还提供了自动化配置和简化开发的特性,让整合过程更加方便快捷。 总结起来,通过整合ElasticsearchSpring Boot,我们可以利用Elasticsearch强大的搜索和存储功能来处理大量的数据,并结合Spring Boot框架的优势快速构建应用程序。 ### 回答3: Elasticsearch是一个基于Lucene的开源搜索和分析引擎,而Spring Boot是一个使用Java快速构建生产级别的应用程序的框架。将ElasticsearchSpring Boot整合可以提供强大的全文搜索和数据分析功能。 首先,我们需要在Spring Boot项目中添加Elasticsearch的依赖。可以通过在pom.xml文件中添加以下代码来实现: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 然后,我们需要创建一个Elasticsearch的配置类,用于配置Elasticsearch的连接信息。可以通过创建一个类,并添加`@Configuration`和`@EnableElasticsearchRepositories`注解来实现: ```java @Configuration @EnableElasticsearchRepositories(basePackages = "com.example.elasticsearch.repository") public class ElasticsearchConfig { @Value("${elasticsearch.host}") private String host; @Value("${elasticsearch.port}") private int port; @Bean public Client client() throws UnknownHostException { Settings settings = Settings.builder() .put("cluster.name", "elasticsearch").build(); TransportClient client = new PreBuiltTransportClient(settings); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), port)); return client; } @Bean public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException { return new ElasticsearchTemplate(client()); } } ``` 在上述代码中,我们通过从配置文件中读取主机和端口信息创建了一个Elasticsearch的客户端连接,并创建了一个用于Elasticsearch操作的ElasticsearchTemplate对象。 接下来,我们可以创建一个持久化层的接口,用于定义Elasticsearch的操作方法。可以通过创建一个接口,并添加`@Repository`注解来实现。例如: ```java @Repository public interface UserRepository extends ElasticsearchRepository<User, String> { List<User> findByName(String name); } ``` 在上述代码中,我们定义了一个UserRepository接口,继承了ElasticsearchRepository接口,并定义了一个按照名字查询用户的方法。 最后,我们可以在业务层或者控制层使用Elasticsearch相关的方法来进行搜索和分析操作。例如,我们可以在服务类中调用UserRepository的方法来实现用户的搜索: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> searchUser(String name) { return userRepository.findByName(name); } } ``` 通过以上步骤,我们就可以在Spring Boot项目中实现Elasticsearch的整合和使用了。通过配置Elasticsearch连接信息、定义操作方法和调用相关方法,可以方便地实现全文搜索和数据分析的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值