前言
SpringBoot+Elasticsearch,通过@Document
注解,利用EL表达式指定到配置文件,实现动态生成IndexName
值,比如:
@Document(indexName = "product_#{@esIndex}")
1、创建动态索引配置文件
在配置文件中按照
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更新索引值 }
2、创建实体
创建的实体类,需要关闭自动创建index属性(
createIndex = false
),通过配置文件来创建索引值,原> 因:如果开启自动索引,在项目启动时的第一个索引会完整创建成功,但是后续通过定时任务创建的索引会缺失配置的shards、replicas参数
;
默认情况下:
createIndex
属性值为true
,在项目启动时就会按照@Document
注解中的配置进行索引的创建,为了包装每次创建索引的完整性,需要将createIndex
属性值为false
@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;
}
3、Repository对象
Repository接口
用于定义Elasticsearch数据访问操作的标准化方法。它提供了一组内置的CRUD(创建、读取、更新、删除)操作,以及其他一些常见的查询方法。
要使用Repository对象
,首先需要定义一个继承自ElasticsearchRepository接口
的自定义接口,用于操作指定的实体类型。该自定义接口通常称为Repository接口
,其中的方法会映射到相应的Elasticsearch数据操作。
比如创建ProductEntity
实体对应的Repository接口
:
public interface ProductRepository extends ElasticsearchRepository<ProductEntity, String> {
}
4、Controller对象
测试时,可以将索引动态更新的
定时任务时间
设置为一分钟
,并且返回的索引值由yyyy_MM_dd
修改为一个随机数
;调用save
方法后,过一分钟
后再次进行调用,通过head/kibana
观察是否生成了新的索引。文章来源:https://www.toymoban.com/news/detail-402660.html
@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);
}
}
文章来源地址https://www.toymoban.com/news/detail-402660.html
到了这里,关于SpringBoot+Elasticsearch按日期实现动态创建索引(分表)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!