ES教程 -- ES命令 | ES JAVA API 学习记录(三)

SpringBoot  ElasticSearch Starter API  

1. pom

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

 2. Elasticsearch Repositories 实现

2.1 定义一个ES映射实体

@Document(indexName = "yourIndexName", shards = 20)
public class EsExampleEntity implements Serializable {

    private static final long serialVersionUID = 2109037559727003184L;

    /**
     * 主键
     */
    @Id
    @Field(type = FieldType.Long)
    private Long id;
    /**
     * 订单号
     */
    @Field(type = FieldType.Keyword)
    private Long orderNo;
    /**
     * 名称
     */
    @Field(type = FieldType.Text)
    private String name;
    /**
     * 创建时间
     */
    @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    private Date gmtCreated;
    /**
     * 销售店铺名称
     */
    @MultiField(mainField = @Field(type = FieldType.Text), otherFields = { @InnerField(type = FieldType.Keyword, suffix = "keyword") })
    private String shopName;
}
Text类型会被分词,KeyWord不会被分词,可以用来做聚合相关操作,如果一个字段又想被分词又想用来做聚合就需要使用 @MultiField 来进行指定

2.2 查询创建

public interface EsExampleRepository extends ElasticsearchRepository<EsExampleEntity, Long> {
}

 注意: @Id指定的字段类型要与本处的泛型类型保持一致

①  按照某字段的升序或降序排序,并分页

写法一

FieldSortBuilder statusSort = SortBuilders.fieldSort("status").order(SortOrder.ASC);
        FieldSortBuilder gmtModifiedSort = SortBuilders.fieldSort("gmtModified").order(SortOrder.DESC);

        Integer current = request.getCurrent();
        Integer size = request.getSize();

        PageRequest pageRequest = PageRequest.of(current - 1, size);
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(mainQuery).withSort(statusSort).withSort(gmtModifiedSort).withSort(SortBuilders.scoreSort()).build();
        searchQuery.setPageable(pageRequest);
        //设置可以查询超过10000条数据
        searchQuery.setTrackTotalHits(true);
        Page<EsCooperationOrderEntity> orderEntities = esCooperationOrderRepository.search(searchQuery);
        Long totalElements = orderEntities.getTotalElements();
        List<EsCooperationOrderEntity> content = orderEntities.getContent();

写法二

Sort.Order gmtModified = new Sort.Order(Sort.Direction.DESC, "gmtModified");
Sort.Order topWeight = new Sort.Order(Sort.Direction.valueOf(param.getSortOrder().name()), param.getSortField().name());
Sort orders = Sort.by(topWeight, gmtModified);

PageRequest pageRequest = PageRequest.of(current - 1, size, orders);
        // 2、es多条件查询
        Page<TalentGoodsEsEntity> entities = talentGoodsEsRepository.search(getBoolQueryBuilder(param), pageRequest);

② 条件查询

public static void main(String[] args) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //模糊查询
        WildcardQueryBuilder spuName = QueryBuilders.wildcardQuery("spuName", "*" + "your searchWord" + "*");
        boolQueryBuilder.must(spuName);
        //精确查询
        boolQueryBuilder.must(QueryBuilders.termQuery("cateNamePath", "your searchWord"));
        //范围查询 filter 必须匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("salePrice").lte("your word"));
        //满足任意一个条件 should
        //当使用should查询时,如果包含了must或者filter查询,那么should的查询语句就不是或者的意思了,而是有或者没有都行的含义。
        List<String> brandNames = new ArrayList<>();
        for (String brandName : brandNames) {
            boolQueryBuilder.should(QueryBuilders.termQuery("brandName", brandName));
        }
        // 参考 https://blog.csdn.net/java_chegnxuyuan/article/details/103025351
        boolQueryBuilder.minimumShouldMatch(1);
    }

③ 聚合查询

@Autowired
    RestHighLevelClient client;

TermsAggregationBuilder liveStartTimeBuilder = AggregationBuilders.terms("liveStartTime").field("liveStartTime");
        TermsAggregationBuilder talentNameBuilder = AggregationBuilders.terms("talentName").field("talentName");
        TermsAggregationBuilder talentIdBuilder = AggregationBuilders.terms("talentId").field("talentId");
        TermsAggregationBuilder liveIdBuilder = AggregationBuilders.terms("liveId").field("liveId");
        TermsAggregationBuilder liveNameBuilder = AggregationBuilders.terms("liveName").field("liveName");

        ValueCountAggregationBuilder spuCount = AggregationBuilders.count("spuCount").field("spuNo");
        ValueCountAggregationBuilder doudianGoodsIdCount = AggregationBuilders.count("doudianGoodsIdCount").field("doudianGoodsId");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        liveStartTimeBuilder.subAggregation(talentIdBuilder);
        talentIdBuilder.subAggregation(talentNameBuilder);
        talentNameBuilder.subAggregation(liveIdBuilder);
        liveIdBuilder.subAggregation(liveNameBuilder);
        liveNameBuilder.subAggregation(spuCount).subAggregation(doudianGoodsIdCount);
        searchSourceBuilder.query(mainQuery).aggregation(liveStartTimeBuilder).size(0);



SearchRequest searchRequest = new SearchRequest("es_coop_order_entity_index_104");
searchRequest.source(searchSourceBuilder);
client.search(searchRequest, RequestOptions.DEFAULT);


List<LiveCalendarVo> liveCalendarVoList = Lists.newArrayList();
        Aggregations aggregations = searchResponse.getAggregations();
        Terms liveStartTimeTerm = aggregations.get("liveStartTime");
        for (Terms.Bucket liveStartTimeBucket : liveStartTimeTerm.getBuckets()) {
            String liveStartTime = liveStartTimeBucket.getKeyAsString();
            Terms talentIdTerm = liveStartTimeBucket.getAggregations().get("talentId");
            for (Terms.Bucket talentIdBucket : talentIdTerm.getBuckets()) {
                String talentId = talentIdBucket.getKeyAsString();
                Terms talentNameTerm = talentIdBucket.getAggregations().get("talentName");
                for (Terms.Bucket talentNameBucket : talentNameTerm.getBuckets()) {
                    String talentName = talentNameBucket.getKeyAsString();
                    Terms liveIdTerm = talentNameBucket.getAggregations().get("liveId");
                    for (Terms.Bucket liveIdBucket : liveIdTerm.getBuckets()) {
                        String liveId = liveIdBucket.getKeyAsString();
                        Terms liveNameTerm = liveIdBucket.getAggregations().get("liveName");
                        for (Terms.Bucket liveNameBucket : liveNameTerm.getBuckets()) {
                            String liveName = liveNameBucket.getKeyAsString();
                            ParsedValueCount spuCount = liveNameBucket.getAggregations().get("spuCount");
                            ParsedValueCount doudianGoodsIdCount = liveNameBucket.getAggregations().get("doudianGoodsIdCount");
                            LiveCalendarVo liveCalendarVo = new LiveCalendarVo();
                            liveCalendarVo.setLiveDate(liveStartTime);
                            liveCalendarVo.setTalentId(talentId);
                            liveCalendarVo.setTalentName(talentName);
                            liveCalendarVo.setLiveId(liveId);
                            liveCalendarVo.setLiveName(liveName);
                            liveCalendarVo.setSpuCount(spuCount.getValue());
                            liveCalendarVo.setDoudianGoodsIdCount(doudianGoodsIdCount.getValue());
                            liveCalendarVoList.add(liveCalendarVo);
                        }
                    }
                }
            }
        }


        //方式二
        //聚合条件
        TermsAggregationBuilder builder1 = AggregationBuilders.terms("taxonomy").field("taxonomy.keyword");
        TermsAggregationBuilder builder2 = AggregationBuilders.terms("year").field("year.keyword");
        TermsAggregationBuilder builder = builder1.subAggregation(builder2);
        //构建查询
        SearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(bqb)
                .withSort(fsb)
                .addAggregation(builder)
                .withPageable(pageable)
                .build();

ES工具类

package com.befriend.first.base.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.alibaba.fastjson.JSONObject;

import com.befriend.common.model.PageVO;
import com.befriend.first.base.constant.GlobalConstant;
import org.elasticsearch.index.query.QueryBuilder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchScrollHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
import org.springframework.data.elasticsearch.core.query.UpdateResponse.Result;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;

/**
 * @author by jlm
 * @date 2021/9/2 10:52 
 */
@Service
public class EsBaseUtils<T> {

    public static final String CONTENT = "content";
    public static final String NEXT_SCROLL_ID = "nextScrollId";
    public static final String TOTAL_COUNT = "totalCount";
    public static final String PAGE_VO = "pageVo";

    @Resource
    ElasticsearchRestTemplate  template;

    /**
     * 该方法用于滚动游标分页 避免深度分页问题 不支持跳页查询
     * @param currentPage 当前页码 从1开始
     * @param size 每页显示数量
     * @param query 查询条件 默认查全部
     * @param scrollId 游标 首次查询为null
     * @param indexName 索引名称
     * @param clazz 查询的Entity class
     * @return
     */
    public Map<String, Object> scrollPage(Integer currentPage, Integer size, QueryBuilder query, String scrollId,
                                          String indexName, Class<T> clazz) {
        IndexCoordinates index = IndexCoordinates.of(indexName);
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(query == null ? matchAllQuery() : query)
            .withPageable(PageRequest.of(currentPage - GlobalConstant.ONE, size))
            .build();

        Map<String, Object>  resultMap = new HashMap<>(GlobalConstant.THREE);
        List<T> sampleEntities = new ArrayList<>();
        long count = template.count(searchQuery, clazz, index);
        if (StringUtils.isEmpty(scrollId)) {
            SearchScrollHits<T> scroll = template.searchScrollStart(30000, searchQuery, clazz, index);
            if (scroll.hasSearchHits()) {
                sampleEntities.addAll(scroll.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList()));
                String nextScrollId = scroll.getScrollId();
                resultMap.put(NEXT_SCROLL_ID, nextScrollId);
            }
        }else {
            SearchScrollHits<T> scrollHits = template.searchScrollContinue(scrollId, 30000, clazz, index);
            if (scrollHits.hasSearchHits()) {
                sampleEntities.addAll(scrollHits.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList()));
                String nextScrollId = scrollHits.getScrollId();
                resultMap.put(NEXT_SCROLL_ID, nextScrollId);
            }
        }
        resultMap.put(CONTENT, sampleEntities);
        resultMap.put(TOTAL_COUNT, count);
        return resultMap;
    }

    /**
     * 获取分页VO 及 nextScrollId
     * @param currentPage
     * @param size
     * @param query
     * @param scrollId
     * @param indexName
     * @param clazz
     * @return
     */
    public Map<String, Object> buildPageVo(Integer currentPage, Integer size, QueryBuilder query, String scrollId, String indexName, Class<T> clazz) {
        Map<String ,Object> finalResMap = new HashMap<>(GlobalConstant.TWO);
        Map<String, Object> resPageMap = scrollPage(currentPage, size, query, scrollId, indexName, clazz);
        Long count = (Long)resPageMap.get(TOTAL_COUNT);
        PageVO<T> pageVO = PageResult.buildResult((List<T>) resPageMap.get(CONTENT), currentPage, size, count.intValue());
        String nextScrollId = (String)resPageMap.get(NEXT_SCROLL_ID);
        finalResMap.put(PAGE_VO, pageVO);
        finalResMap.put(NEXT_SCROLL_ID, nextScrollId);
        if (!pageVO.getHasNext()) {
            searchScrollClear(nextScrollId);
        }
        return finalResMap;
    }

    /**
     * 清除ScrollId
     * @param scrollId
     */
    public void searchScrollClear(String scrollId) {
        template.searchScrollClear(Arrays.asList(scrollId));
    }

    /**
     * 更新es部分字段数据
     * @param esEntity
     * @param id
     */
    public boolean updateEsEntityById(T esEntity, String id) {
        Class<?> aClass = esEntity.getClass();
        Document annotation = aClass.getAnnotation(Document.class);
        String indexName = annotation.indexName();

        Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(esEntity), Map.class);
        org.springframework.data.elasticsearch.core.document.Document document = org.springframework.data.elasticsearch.core.document.Document.create();

        for (Entry<String, Object> stringObjectEntry : map.entrySet()) {
            document.put(stringObjectEntry.getKey(), stringObjectEntry.getValue());
        }

        UpdateResponse response = getUpdateResponse(id, indexName, document);
        return Result.UPDATED.equals(response.getResult());
    }

    /**
     * 设置某字段为null
     * @param indexName
     * @param fieldName
     * @param id
     * @return
     */
    public boolean setFieldNullById(String indexName, String fieldName, String id) {
        org.springframework.data.elasticsearch.core.document.Document document = org.springframework.data.elasticsearch.core.document.Document.create();
        document.put(fieldName, null);
        UpdateResponse response = getUpdateResponse(id, indexName, document);
        return Result.UPDATED.equals(response.getResult());
    }

    private UpdateResponse getUpdateResponse(String id, String indexName,
                                             org.springframework.data.elasticsearch.core.document.Document document) {
        UpdateQuery build = UpdateQuery.builder(id).withDocument(document).build();
        return template.update(build, IndexCoordinates.of(indexName));
    }

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值