SpringBoot+Elasticsearch按日期实现动态创建索引

  Java   10分钟   354浏览   0评论

😊 @ 作者: 召田最帅boy
💖 @ 主页: https://www.hqxiaozou.top
🎉 @ 主题: SpringBoot+Elasticsearch按日期实现动态创建索引
⏱️ @ 创作时间: 2023年02月21日

前言

SpringBoot+Elasticsearch,通过@Document注解,利用EL表达式指定到配置文件,实现动态生成IndexName值,比如:

@Document(indexName = "product_#{@esIndex}")

创建动态索引配置文件

在配置文件中按照yyyy_MM_dd格式返回索引值的后缀,并且通过定时任务对索引值实现更新操作,定时任务是通过重建Bean对象实现对esIndex值进行更新。

重建Bean原因:Bean默认只有在服务启动时加载,若需动态改变Bean就要先销毁这个Bean之后再重新加载。

@Configuration
public class EsIndexConfig {

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Bean(name = "esIndex")
    public static String esIndex() {
        // 此处模拟按日期创建索引
        // 由于方便测试,索引直接返回时间戳,作为索引名称,时间可以为yyyy-MM-dd
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd");
        String date = sdf.format(new Date());
        System.out.println(date);

        date = System.currentTimeMillis() / 1000 + "";
        System.out.println("date:" + date);
        return date;
    }

    // 每天0点
    @Scheduled(cron = "0 0 0 * * ?")
    public void updateEsIndex() {
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        // 销毁指定实例
        defaultListableBeanFactory.destroySingleton("esIndex");
        String index = EsIndexConfig.esIndex();
        // 重新注册
        defaultListableBeanFactory.registerSingleton("esIndex", index);

        // 对索引进行一次手动创建(因为自动创建会丢失shards参数)
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(ProductEntity.class);
        if (!indexOperations.exists()) {
            indexOperations.create();
        }
    }
}

其他做法:
也可以不通过定时任务更新索引值,可以在操作save方法前,判断索引是否存在,如果不存在再进行重建Bean更新索引值,如下实例:

IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(ProductEntity.class);
if (!indexOperations.exists()) {
    索引不存在,则重建Bean更新索引值
}

创建实体

创建的实体类,需要关闭自动创建index属性(createIndex = false),通过配置文件来创建索引值,原因:如果开启自动索引,在项目启动时的第一个索引会完整创建成功,但是后续通过定时任务创建的索引会缺失配置的shards、replicas参数

@Document(indexName = "product_#{@esIndex}", createIndex = false, shards = 3, replicas = 2)
@Data
public class ProductEntity implements Serializable {

    @Id
    private String id;

    /**
     * 文本类型,使用ik分词器
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String name;

    /**
     * 价格
     */
    @Field(type = FieldType.Double)
    private BigDecimal money;

    /**
     * 时间戳
     */
    @Field(type = FieldType.Long)
    private Long time;

    /**
     * 颜色
     */
    @Field(type = FieldType.Keyword)
    private String color;
}

Repository对象

public interface ProductRepository extends ElasticsearchRepository<ProductEntity, String> {

}

Controller对象

测试时,可以将索引动态更新的定时任务时间设置为一分钟,并且返回的索引值由yyyy_MM_dd修改为一个随机数;调用save方法后,过一分钟后再次进行调用,通过head/kibana观察是否生成了新的索引。

@RestController
@RequestMapping("es")
@Slf4j
public class ProductController {

    @Resource
    private ProductRepository productRepository;

    @PostMapping
    public void save() {
        String[] colors = {"red", "purple", "blue"};
        String[] name = {"手机", "电脑", "微波炉", "电视"};
        // 新增列表数据
        List<ProductEntity> testList = new ArrayList<>();
        long sys = System.currentTimeMillis();
        for (int i = 0; i < 10; i++) {
            // 模拟随机数
            double random = Math.random() * 1000;

            ProductEntity productEntity = new ProductEntity();
            productEntity.setId(i + "");
            productEntity.setName(name[i % 4]);
            productEntity.setMoney(new BigDecimal(random));
            productEntity.setTime(sys + i % 3);
            productEntity.setColor(colors[i % 3]);
            testList.add(productEntity);
        }
        // 新增成功后,在head或者kibana中就可以看到相应数据,如果save时数据Id存在则更新操作
        // 批量新增
        productRepository.saveAll(testList);

        // 单个新增
        ProductEntity productEntity = testList.get(9);
        productEntity.setId("11");
        productRepository.save(productEntity);
    }
}
如果你觉得文章对你有帮助,那就请作者喝杯咖啡吧☕
微信
支付宝
  0 条评论