es模板批量保存的坑

前言:

今天写项目时,发现了我们封装的es模板方法save的批量保存的一个巨大的坑,导致我数据保存一直数据错乱,仔细检查了代码没有问题,然后转向去看封装方法,才知道这么霸道,可能是为了提升性能吧!!!

代码:

模型类:

package com.saascloud.scms.bi.model;

import com.saascloud.common.esclient.annotation.ESID;
import com.saascloud.common.esclient.annotation.ESMapping;
import com.saascloud.common.esclient.annotation.ESMetaData;
import com.saascloud.common.esclient.enums.DataType;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

@ESMetaData(indexName = "item-sales-report", indexType = "item-sales-report", suffix = "-customerId", suffixDateType = 1, number_of_shards = 5, number_of_replicas = 0, printLog = true)
@Data
public class ItemSalesReport implements Serializable {

    @ESID
    private String id;

    @ESMapping(datatype = DataType.keyword_type)
    private String tenantId;

    @ESMapping(datatype = DataType.keyword_type)
    private String warehouseId;

    @ESMapping(datatype = DataType.keyword_type)
    private String warehouseName;

    @ESMapping(datatype = DataType.keyword_type)
    private String warehouseCode;

    @ESMapping(datatype = DataType.keyword_type)
    private String customerId;

    @ESMapping(datatype = DataType.keyword_type)
    private String customerCode;

    @ESMapping(datatype = DataType.keyword_type)
    private String customerName;

    @ESMapping(datatype = DataType.keyword_type)
    private String itemId;

    @ESMapping(datatype = DataType.keyword_type)
    private String itemCode;

    @ESMapping(datatype = DataType.keyword_type)
    private String itemName;

    @ESMapping(datatype = DataType.keyword_type)
    private String barCode;

    /**
     * 商品尺码
     */
    @ESMapping(datatype = DataType.keyword_type)
    private String size;

    /**
     * 规格型号
     */
    @ESMapping(datatype = DataType.keyword_type)
    private String skuProperty;

    /**
     * 商品单位
     */
    @ESMapping(datatype = DataType.keyword_type)
    private String stockUnit;

    /**
     * 商品颜色
     */
    @ESMapping(datatype = DataType.keyword_type)
    private String color;

    /**
     * 一级包装
     */
    @ESMapping(datatype = DataType.double_type)
    private BigDecimal boxQuantity;

    /**
     * 商品品类
     */
    @ESMapping(datatype = DataType.keyword_type)
    private String itemGroupName;

    /**
     * 操作时间
     */
    @ESMapping(datatype = DataType.date_type)
    private Date operatorDate;

    @ESMapping(datatype = DataType.keyword_type)
    private String operatorName;

    /**
     * 销售总量
     */
    @ESMapping(datatype = DataType.double_type)
    private BigDecimal saleQty;

    /**
     * 销售总额
     */
    @ESMapping(datatype = DataType.double_type)
    private BigDecimal saleAmount;

    /**
     * 成本总额
     */
    @ESMapping(datatype = DataType.double_type)
    private BigDecimal costAmount;

    /**
     * 商品货号
     */
    @ESMapping(datatype = DataType.keyword_type)
    private String itemGoodsCode;

    /**
     * 商品等级
     */
    @ESMapping(datatype = DataType.keyword_type)
    private String itemLevel;

    /**
     * 统计月份
     */
    @ESMapping(datatype = DataType.keyword_type)
    private String month;
}

保存方法:

package com.saascloud.scms.bi.rpc;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.saascloud.api.common.dto.oms.ItemSalesReportDTO;
import com.saascloud.auth.client.core.annotation.IgnoreUserToken;
import com.saascloud.common.base.msg.ObjectRestResponse;
import com.saascloud.common.core.util.SnowFlakeUtil;
import com.saascloud.common.esclient.index.ElasticsearchIndex;
import com.saascloud.common.esclient.index.IndexParam;
import com.saascloud.common.esclient.repository.ElasticsearchTemplate;
import com.saascloud.common.esclient.util.IndexTools;
import com.saascloud.common.esclient.util.JsonUtils;
import com.saascloud.common.esclient.util.MetaData;
import com.saascloud.scms.bi.model.ItemSalesReport;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@RequestMapping("api")
@Slf4j
public class ItemSalesReportRest {

    @Autowired
    ElasticsearchTemplate<ItemSalesReport, String> els;

    @Autowired
    ElasticsearchIndex elasticsearchIndex;

    /**
     * 保存商品销量记录
     *
     * @param params
     * @return
     */
    @RequestMapping(value = "/itemSalesReport/save", method = RequestMethod.POST)
    @IgnoreUserToken
    @ResponseBody
    public ObjectRestResponse save(@RequestBody List<ItemSalesReportDTO> params) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            log.info("保存商品销量记录请求报文:{}", params.toString());
            List<ItemSalesReport> itemSalesReportList = new ArrayList<>();
            params.forEach(item -> {
                ItemSalesReport itemSalesReport = new ItemSalesReport();
                BeanUtil.copyProperties(item, itemSalesReport);
                itemSalesReport.setId(String.valueOf(SnowFlakeUtil.getFlowIdInstance().nextId()));
                itemSalesReportList.add(itemSalesReport);
            });
            // 批量保存的集合中不允许出现跟索引后缀不一样的数据
            // 比如索引后缀customerId为3,集合中就不允许出现customerId为4的数据,否则会导致数据错乱
            els.save(itemSalesReportList);
        } catch (Exception e) {
            log.info("保存商品销量记录错误,错误信息:{}", e);
        }
        return new ObjectRestResponse<>().data(resultMap);
    }
}


准备好了么?下面上坑的地方:

在这里插入图片描述
在这里插入图片描述
看出问题来了么,假如你现在6条数据,三条的customerId为3,另外3条的customerId为4,而你想一次性保存,如果获取的第一个数据的customerId为4,则6条数据都会被存入item-sales-report-4的索引中,导致数据错乱!!!

解决方法:

第一种方法:

对集合进行分组,将后缀同样的数据一次性批量保存。

第二种方法:

处理完同样后缀的数据后形成集合保存掉,再进行下一轮同样后缀的数据处理。

总结:

后台不报错,建议还是底层封装吧!!!菜鸡爬坑真的太难了!!!

发布了3 篇原创文章 · 获赞 5 · 访问量 1176
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览