04|Elasticsearch简单的增删改查

140 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情

1.创建Index

在这里我们不建议通过java api的方式创建索引,因为在实际的生当中,创建索引一般我们是要提工单通过运维去操作,创建索引的。我们只需要提供创建索引的json命令文件即可。

现在我们在kibana的界面,通过Dev Tools来创建一个索引。

假设实际这是我们的一个电商业务,我们在真个业务过程当中,商品的信息是需要不断的被检索的,所以在这我们建一个商品信息的索引。

主要包含的信息大概有商品唯一id、商品名称、商品标签价格,商品实际销售价格、库存、skuId等等,创建index的命令如下:

PUT /goods_item_index
{
    "settings": {
        "number_of_shards": 3, 
        "number_of_replicas": 1
    }, 
    "mappings": {
        "properties": { 
            "@timestamp": {
              "type": "date"
            },
            "category": {
                "type": "keyword"
            }, 
            "basePrice": {
                "type": "double"
            }, 
            "marketPrice": {
                "type": "double"
            }, 
            "stockNum": {
                "type": "integer"
            }, 
            "skuImgUrl": {
                "type": "keyword", 
                "index": false
            }, 
            "skuId": {
                "type": "keyword"
            }, 
            "skuName": {
                "type": "text"
            },
            "createTime": {
                "type": "date", 
                "format": "yyyy-MM-dd HH:mm:ss"
            }, 
            "updateTime": {
                "type": "date", 
                "format": "yyyy-MM-dd HH:mm:ss"
            }
            
        }
    }
}

我们通过kibana创建这个索引。

image-20221120131433787.png

右侧显示如下表示成功

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "goods_item_index"
}

2.新增

接下来我们通过kibana创建一条数据,我们通过PUT命令新增一条数据,PUT方式添加文档,如果不存在,则创建,如果存在,则更新,PUT方式添加文档,必须指定id。如果没有ID,提示以下错误。

image-20221120140143740.png 创建命令如下 ``` PUT goods_item_index/_doc/1 { "category": "phone", "basePrice": 1500.00, "marketPrice": 1000.00, "stockNum": 100, "skuImgUrl": "http://www.xxxx.com?dsdsds", "skuId": "p23232", "skuName": "华为手机", "createTime": "2022-01-01 00:00:00", "updateTime": "2022-01-01 00:00:00" } ``` 创建成功如下 image-20221120140332677.png 接下来我们通过java api创建

先创建entity实体类用于跟ES进行交互 GoodsItems.java

@Data
public class GoodsItem {
    private Long id;

    private String category;

    private BigDecimal basePrice;

    private BigDecimal marketPrice;

    private Integer stockNum;

    private String skuImgUrl;

    private String skuId;

    private String skuName;

    @DateTimeFormat(pattern = "yyyy-mm-dd HH:mm:ss")
    private Date createTime;

    @DateTimeFormat(pattern = "yyyy-mm-dd HH:mm:ss")
    private Date updateTime;
}

创建响应类跟请求类

com.daiyu.elastic.domain.request.GoodsItemReq.java

@Data
public class GoodsItemReq {
    private Long id;

    private String category;

    private BigDecimal basePrice;

    private BigDecimal marketPrice;

    private Integer stockNum;

    private String skuImgUrl;

    private String skuId;

    private String skuName;

    @DateTimeFormat(pattern = "yyyy-mm-dd HH:mm:ss")
    private Date createTime;

    @DateTimeFormat(pattern = "yyyy-mm-dd HH:mm:ss")
    private Date updateTime;
}

com.daiyu.elastic.domain.reponse.GoodsItemRep.java

@Data
public class GoodsItemRep {
    private Long id;

    private String category;

    private BigDecimal basePrice;

    private BigDecimal marketPrice;

    private Integer stockNum;

    private String skuImgUrl;

    private String skuId;

    private String skuName;

    @DateTimeFormat(pattern = "yyyy-mm-dd HH:mm:ss")
    private Date createTime;

    @DateTimeFormat(pattern = "yyyy-mm-dd HH:mm:ss")
    private Date updateTime;
}

service接口com.daiyu.elastic.service.GoodsService

/**
     * 单条插入
     *
     * @param goodsItemReq 请求体
     * @return 成功与否
     */
    Boolean insertGoods(GoodsItemReq goodsItemReq);

接口实现类com.daiyu.elastic.service.GoodsServiceImpl,新增方法

    @Override
    public Boolean insertGoods(GoodsItemReq goodsItemReq) {
        GoodsItem goodsItem = new GoodsItem();
        BeanUtils.copyProperties(goodsItemReq, goodsItem);
        Result insert = client.insert(goodsItemReq.getSkuId(), index, goodsItem);
        if (insert == Result.Updated) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

controller,com.daiyu.elastic.controller.GoodsController.java

    @PostMapping("/insertGoods")
    @ResponseBody
    private BaseResponse<Boolean> insertGoods(@RequestBody GoodsItemReq goodsItemReq) {
        BaseResponse<Boolean> baseResponse = new BaseResponse<>();
        baseResponse.setData(goodsService.insertGoods(goodsItemReq));
        baseResponse.setCode(200);
        baseResponse.setMsg("插入成功");
        return baseResponse;
    }

接下来我们通过,postman等工具对接口进行起请求

curl --location --request POST 'http://localhost:8089/goods/insertGoods' \
--header 'Content-Type: application/json' \
--data-raw '{
  "id": 2,
  "category": "phone",
  "basePrice": 1000.00,
  "marketPrice": 900.00,
  "stockNum": 100,
  "skuImgUrl": "http://www.xiaom.com?dsdsds",
  "skuId": "p1000001",
  "skuName": "小米手机",
  "createTime": "2022-01-01 00:00:00",
  "updateTime": "2022-01-01 00:00:00"
}'

成功结果如下

image-20221120152406560.png 接下来测试一下批量插入,为了避免过多无用代码,从下面开始只展示关键代码逻辑,全部代码可在提供的资料里查看。

现在GoodsService新增批量插入方法

     /**
      * 批量插入
      *
      * @param goodsItemReqs 请求体
      * @return 成功与否
      */
     Boolean bulkInsertGoods(List<GoodsItemReq> goodsItemReqs);

实现方法

 @Override
     public Boolean bulkInsertGoods(List<GoodsItemReq> goodsItemReqs) {
         List<GoodsItem> goodsItems = new ArrayList<>();
         for (GoodsItemReq goodsItemReq : goodsItemReqs) {
             GoodsItem goodsItem = new GoodsItem();
             BeanUtils.copyProperties(goodsItemReq, goodsItem);
             goodsItems.add(goodsItem);
         }
 ​
         BulkRequest.Builder br = new BulkRequest.Builder();
 ​
         for (GoodsItem goodsItem : goodsItems) {
             br.operations(op -> op      
                     .index(idx -> idx
                             .index(index)
                             .id(goodsItem.getId().toString())
                             .document(goodsItem)
                     )
             );
         }
         return client.bulkInsert(br);
     }

ElasticsearchUtil工具类新增批量插入通用方法

 /**
      * 批量插入
      *
      * @param br build
      * @throws IOException
      */
     public Boolean bulkInsert(BulkRequest.Builder br) {
         BulkResponse bulkResponse = null;
         try {
             bulkResponse = client.bulk(br.build());
         } catch (IOException e) {
             log.info(e.getMessage(), e);
         }
 ​
         if (bulkResponse.errors()) {
             log.error("插入存在错误");
             for (BulkResponseItem item : bulkResponse.items()) {
                 if (item.error() != null) {
                     log.error(item.error().reason());
                 }
             }
             return false;
         } else {
             log.info("全部插入完成");
             return true;
         }
     }

然后通过postman等工具对接口进行起请求

op 是一个构建器,BulkOperation它是一个构造器。此类型可以进行indexcreateupdatedelete操作的构建。

curl --location --request POST 'http://localhost:8089/goods/bulkInsertGoods' \
--header 'Content-Type: application/json' \
--data-raw '[
    {
  "id": 3,
  "category": "phone",
  "basePrice": 1000.00,
  "marketPrice": 900.00,
  "stockNum": 100,
  "skuImgUrl": "http://www.xiaom.com?dsdsds",
  "skuId": "p1000001",
  "skuName": "vivo手机",
  "createTime": "2022-01-01 00:00:00",
  "updateTime": "2022-01-01 00:00:00"
},
{
  "id": 4,
  "category": "phone",
  "basePrice": 1000.00,
  "marketPrice": 900.00,
  "stockNum": 100,
  "skuImgUrl": "http://www.xiaom.com?dsdsds",
  "skuId": "p1000001",
  "skuName": "oppo手机",
  "createTime": "2022-01-01 00:00:00",
  "updateTime": "2022-01-01 00:00:00"
}
]'
image-20221120163013252.png ### 3.查询

根据ID进行查询

在service里边新增方法

    /**
     * 根据ID进行查询
     *
     * @param id id
     * @return 响应结果
     */
    List<GoodsItemRep>  queryById(Long id);

方法的具体实现

 @Override
   public List<GoodsItemRep> queryById(Long id) {
       Query query = MatchQuery.of(m -> m
               .query(id.toString())
       )._toQuery();
       List<GoodsItem> result = client.search(index, GoodsItem.class, query);
       List<GoodsItemRep> goodsItemReps = new ArrayList<>();

       for (GoodsItem goodsItem : result) {
           GoodsItemRep goodsItemRep = new GoodsItemRep();
           BeanUtils.copyProperties(goodsItem, goodsItemRep);
           goodsItemReps.add(goodsItemRep);
       }

       return goodsItemReps;
   }

通过postman查询结构

curl --location --request GET 'http://localhost:8089/goods/queryGoodsById?id=3'
image-20221120165919175.png ### 4.修改

根据id进行修改,这里我们只需要调用client的insert方法即可,只要我们的_id跟es里边的数据存在的Id对应即可。

   @Override
    public Boolean updateGoods(GoodsItemReq goodsItemReq) {
        GoodsItem goodsItem = new GoodsItem();
        BeanUtils.copyProperties(goodsItemReq, goodsItem);
        Result insert = client.insert(goodsItemReq.getId().toString(), index, goodsItem);
        if (insert == Result.Updated) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

postman进行接口请求

curl --location --request POST 'http://localhost:8089/goods/updateGoods' \
--header 'Content-Type: application/json' \
--data-raw '{
  "id": 2,
  "category": "phone",
  "basePrice": 1000.00,
  "marketPrice": 900.00,
  "stockNum": 100,
  "skuImgUrl": "http://www.xiaom.com?dsdsds",
  "skuId": "p1000001",
  "skuName": "小米手机2222",
  "createTime": "2022-01-01 00:00:00",
  "updateTime": "2022-01-01 00:00:00"
}'
image-20221120170659583.png 然后我们通过kibana查看修改结果,可以看到_id为2的skuName已经被揍改为了"小米手机2222" ``` GET goods_item_index/_search { "query": { "term": { "_id": 2 } } } ``` image-20221120170757247.png ### 5.删除

虽然说,es不建议修改或者删除数据,但是我们还是要学习一下删除的API操作

在service新增删除方法

    /**
     * @param id 根据ID进行删除
     * @return 成功与否
     */
    Boolean deleteGoodsById(Long id);

实现类 的方法

    @Override
    public Boolean deleteGoodsById(Long id) {
        Result result = client.deleteById(index, id.toString());
        if (result == Result.Deleted) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

在ElasticsearchUtil工具类新增根据id删除数据的方法

 /**
     * 根据_id删除索引数据
     *
     * @param index 索引名称
     * @param id    _id
     * @return
     */
    public Result deleteById(String index, String id) {
        DeleteResponse deleteResponse = null;
        try {
            deleteResponse = client.delete(d -> d.index(index).id(id));
        } catch (IOException e) {
            log.info(e.getMessage(), e);
        }
        return deleteResponse.result();
    }

在postman里边调用,删除_id为1的数据

curl --location --request POST 'http://localhost:8089/goods/deleteGoodsById?id=1'
image-20221120172038270.png 然后在kibana查询这条数据是否存在
 GET goods_item_index/_search
 {
   "query": {
     "term": {
       "_id": 1
     }
   }
 }

可以看到_id为1的数据成功删除

image-20221120172403287.png 至此我们简单的增删改查操作完成。