如何在Spring Elasticsearch中通过一行代码批量Upsert/更新多个索引?
如何将多类型Elasticsearch索引的批量Upsert操作优化为一行代码调用?
现有实现代码
你目前有一个泛型的批量更新/Upsert方法,用于Elasticsearch文档操作:
@Override public void bulkUpdate(List<T> objectList) { if (objectList.isEmpty()) { return; } List<UpdateQuery> updateList = new ArrayList<>(); for (T st : objectList) { UpdateQuery updateQuery = UpdateQuery.builder(st.getId()) .withDocument(this.operations.getElasticsearchConverter().mapObject(st)) .withDocAsUpsert(true) .build(); updateList.add(updateQuery); } this.operations.bulkUpdate(updateList, this.operations.getIndexCoordinatesFor(this.entityClass)); }
调用时需要分别调用不同Repository的方法:
public void callUpdate (){ personRepository.bulkUpdate(personList); addressRepository.bulkUpdate(addressList); phoneNumberRepository.bulkUpdate(phoneNumberList); }
优化方案:统一批量处理方法
当然可以优化为一行代码完成所有操作,核心思路是封装一个通用处理方法,接收「Repository + 对应数据列表」的组合,批量执行更新。
1. 定义数据载体(Java 16+推荐用Record)
用Record可以简洁地封装Repository和对应的数据列表:
record RepositoryDataPair<T>(BulkUpdateRepository<T> repository, List<T> data) {}
注:BulkUpdateRepository是你的Repository接口类型,需替换为实际接口名
2. 编写统一处理方法
如果想支持可变参数(更简洁),可以定义如下方法:
@SafeVarargs public final void bulkUpdateAll(RepositoryDataPair<?>... updatePairs) { Arrays.stream(updatePairs) .filter(pair -> !pair.data().isEmpty()) .forEach(pair -> pair.repository().bulkUpdate(pair.data())); }
3. 一行代码调用
现在只需要一行调用即可完成所有类型的批量Upsert:
bulkUpdateAll(new RepositoryDataPair<>(personRepository, personList), new RepositoryDataPair<>(addressRepository, addressList), new RepositoryDataPair<>(phoneNumberRepository, phoneNumberList));
如果追求可读性,也可以换行书写,但逻辑上仍属于单个方法调用
额外说明
- 这种方式既保留了你原有的
bulkUpdate方法逻辑,又通过统一入口减少了重复调用代码 - 如果使用Java 16以下版本,可将Record替换为普通POJO类,添加对应的构造器和Getter方法
- 统一方法里的空列表判断是可选的(原方法已经处理),但加上可以避免不必要的方法调用开销
内容的提问来源于stack exchange,提问作者Java2Avaj
相关产品推荐
相关产品推荐

