不是哥们?你的ES还在单索引存储,赶紧用动态索引吧

646 阅读3分钟

前言

在索引的使用中,我们有单索引,以及使用多索引,主要有以下的原因

单个索引适合:

  • 数据量相对较小且结构相似的场景。

  • 对管理简单性要求较高的环境。

  • 数据写入频率较低且查询模式简单的场景。

单个索引不适合:

  • 数据量非常庞大或增长较快的场景。

  • 数据结构差异较大,或者不同类型的数据需要不同的查询优化的场景。

  • 需要横向扩展的环境,尤其是对伸缩性要求高时。

因此我们在数据量比较大的时候,例如日志,告警,订单等等场景的时候,是可以考虑用动态索引的,例如可以按月份进行。

以及在按月份统计的时候,也是有好处的,可以直接用月份进行统计,可以节省资源。

以Easy-es为基础,如果不知道Easy-es如何使用的话,可以重新学习一下该文章

Easy-es太绝了,妈妈再也不用担心es太难用了_easyes详解-CSDN博客

实现

本文就以订单为例子,教你如何实现Es的动态索引的实现。

订单有订单时间,按订单时间的月份作为索引区分

例如 订单时间为:2025-01-10 10:10:10 则插入**order_info2025_01**索引

使用依赖

        <dependency>
            <groupId>org.dromara.easy-es</groupId>
            <artifactId>easy-es-boot-starter</artifactId>
            <!--这里Latest Version是指最新版本的依赖,比如2.0.0,可以通过下面的图片获取-->
            <version>2.0.0</version>
        </dependency>

实体类

package com.walker.es.dynamicIndex;


import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.IndexId;
import org.dromara.easyes.annotation.IndexName;
import org.dromara.easyes.annotation.rely.Analyzer;
import org.dromara.easyes.annotation.rely.FieldType;

import java.io.Serializable;

@Data
//设置别名
@IndexName(value = "order_info", aliasName = "order")
public class OrderEntity implements Serializable {

    //    一定要设置 否则会报错
    @IndexId
    private String esId;

    //    订单id
    @IndexField(value = "orderId", fieldType = FieldType.KEYWORD)
    private String orderId;
    //    产品名称
    @IndexField(value = "productName", fieldType = FieldType.TEXT, analyzer = Analyzer.IK_MAX_WORD)
    private String productName;
    //    用户
    @IndexField(value = "name", fieldType = FieldType.TEXT)
    private String userName;
    //    下单时间
    @IndexField(value = "orderTime", fieldType = FieldType.KEYWORD)
    private String orderTime;

    //    索引
    @IndexField(exist = false)
    private final static String INDEX_PREFIX = "order_info";

    //    别名
    @IndexField(exist = false)
    private final static String INDEX_ALIAS = "order";


//    在实体类中 不要轻易使用getXX方法,如果不是类的属性的话,
//    否则会导致序列化的时候报错
//    如果要使用 则得使用     @JSONField(serialize = false)  // 这个字段不会被序列化
    //    按照月份获取索引
    public String index() {
        return INDEX_PREFIX + DateUtil.format(DateUtil.parseDateTime(orderTime), "yyyy_MM");
    }

    public static String indexAlias() {
        return INDEX_ALIAS;
    }
}


模拟下单接口

基本实现逻辑如此

图片

画板

这里模拟了10条数据,每次的订单的时间都往后1个月,看看会产生多少个索引。

 @PostMapping
    public void createDatas() {
        Date date = new Date();
        for (int i = 1; i < 11; i++) {
            OrderEntity orderEntity = new OrderEntity();
            orderEntity.setEsId(UUID.randomUUID().toString());
            orderEntity.setOrderId(String.valueOf(i));
            orderEntity.setProductName(RandomUtil.getRandomChineseString(5));
            orderEntity.setUserName(RandomUtil.getRandomChineseString(3));
//            时间每次都往后一个月 看看会创建多少索引
            date=DateUtil.offsetMonth(date,1);
            orderEntity.setOrderTime(date.toString());
            //            获取索引
            String index = orderEntity.index();
//            查询索引是否存在
            if(!orderEsMapper.existsIndex(index)){
                orderEsMapper.createIndex(index);
            }

            orderEsMapper.insert(orderEntity,index);
        }
    }

执行接口后,看看产生的结果:

图片

可以看到生成了10个索引数据

图片

以及别名都是order,这个是有用处的,我们后面看看就知道了.

模拟数据分页查询接口

    @PostMapping("/search")
    public List<OrderEntity> search() {
        LambdaEsQueryWrapper<OrderEntity> wrapper = new LambdaEsQueryWrapper<>();
//       设置索引别名
        wrapper.index(OrderEntity.indexAlias());
        return orderEsMapper.selectList(wrapper);
    }

设置索引别名,用的是将匹配的索引别名的数据都查询到,

我们这里后续可以做这样的逻辑,对于已经不需要的月份索引修改别名,或者直接删除即可。

那我们先看看查询结果,我们刚刚插入了10条数据,看看返回结果是否是10条

图片

可以看到,确实是有10条数据的。

项目源码

如果需要源码,可以关注一下公众号I am Walker,回复项目源码即可

总结

基本上动态索引就是如此的简单了,我们主要是要有这个思想,在设计阶段要对其进行考虑。

往期ES文章如下:

Easy-es 太绝了!

ES最常用的中文、拼音分词器你还不会??

还在用普通的日志查询?ELK赶紧用起来!

Springboot整合spring-boot-starter-data-elasticsearch

Springboot整合Elasticsearch(官方依赖)

本文使用 文章同步助手 同步