使用批量更新 elasticsearch 实体
Updating elasticsearch entities with bulk
我有以下数据库数据 (ES 7.xx) 版本
{
"id":"1234",
"expirationDate":"17343234234",
"paths":"http:localhost:9090",
"work":"software dev",
"family":{
"baba":"jams",
"mother":"ela"
}
},
{
"id":"00021",
"expirationDate":"0123234",
"paths":"http:localhost:8080",
"work":"software engi",
"family":{
"baba":"stev",
"mother":"hela"
}
}
如何更新到期日期小于当前时间的实体?例如当前时间:
ID 00021 已过期,因为它的过期日期比今天小,因此应更新为当前时间。
类似 void updateExpiredEntity(List<ids> ids,Long currentTime)
起诉 void bulkUpdate(List<UpdateQuery> queries, BulkOptions bulkOptions, IndexCoordinates index);
请提供一些代码实现
这样正确吗?
public void update(UUID id,Long currentDate) {
UpdateQuery updateQuery = UpdateQuery.builder(id.toString()).withRouting("expirationDate=currentDate")
.build();
elasticsearchTemplate.bulkUpdate(List.of(updateQuery), IndexCoordinates.of("index"));
}
}
如果您使用的是 Elasticsearch 7.xx,我假设您使用的是 Spring Data Elasticsearch 版本 4。0.x 随 Spring boot 2.3.x。因为是支持Elasticsearch的版本7.xx.
此 Spring Data Elasticsearch 版本中有很多更改。通过查询更新文档就是其中之一。与之前我们自动装配 ElasticsearchTemplate 不同,我们现在必须改用 ElasticsearchRestTemplate 和 RestHighLevelClient。
在您的情况下,您可能希望使用 RestHighLevelClient 通过查询更新文档。假设您将 expirationDate 存储为以秒为单位的数字映射类型,那么您要求的代码应该如下所示。
public class ElasticsearchService {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Autowired
private RestHighLevelClient highLevelClient;
public void updateExpireDateDemo() throws IOException {
String indexName = "test";
Date currentDate = new Date();
Long seconds = (Long) (currentDate.getTime() / 1000);
UpdateByQueryRequest request = new UpdateByQueryRequest(indexName);
request.setQuery(new RangeQueryBuilder("expirationDate").lte(seconds));
Script updateScript = new Script(
ScriptType.INLINE, "painless",
"ctx._source.expirationDate=" + seconds + ";",
Collections.emptyMap());
request.setScript(updateScript);
highLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
}
}
我不太明白为什么您真的需要使用 bulkUpdate,但如果是这样的话。您必须首先从 Elasticsearch 查询需要更新的记录以获取每个文档的 ID。然后您可以使用 UpdateQuery 列表进行更新。所以您的代码将如下所示。
@Service
public class ElasticsearchService {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
public void updateExpireDateByBulkDemo() throws IOException {
String indexName = "test";
Date currentDate = new Date();
Long seconds = (Long) (currentDate.getTime() / 1000);
List<UpdateQuery> updateList = new ArrayList();
RangeQueryBuilder expireQuery = new RangeQueryBuilder("expirationDate").lte(seconds);
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(expireQuery).build();
SearchHits<Data> searchResult = elasticsearchRestTemplate.search(query, Data.class, IndexCoordinates.of(indexName));
for (SearchHit<Data> hit : searchResult.getSearchHits()) {
String elasticsearchDocumentId = hit.getId();
updateList.add(UpdateQuery.builder(elasticsearchDocumentId).withScript("ctx._source.expirationDate=" + seconds + ";").build());
}
if (updateList.size() > 0) {
elasticsearchRestTemplate.bulkUpdate(updateList, IndexCoordinates.of(indexName));
}
}
}
但是,这只会更新搜索结果的第一页。如果您需要更新与您的查询匹配的每条记录,那么您必须使用 searchScroll 方法来获取每个文档 ID。
我有以下数据库数据 (ES 7.xx) 版本
{
"id":"1234",
"expirationDate":"17343234234",
"paths":"http:localhost:9090",
"work":"software dev",
"family":{
"baba":"jams",
"mother":"ela"
}
},
{
"id":"00021",
"expirationDate":"0123234",
"paths":"http:localhost:8080",
"work":"software engi",
"family":{
"baba":"stev",
"mother":"hela"
}
}
如何更新到期日期小于当前时间的实体?例如当前时间:
ID 00021 已过期,因为它的过期日期比今天小,因此应更新为当前时间。
类似 void updateExpiredEntity(List<ids> ids,Long currentTime)
起诉 void bulkUpdate(List<UpdateQuery> queries, BulkOptions bulkOptions, IndexCoordinates index);
请提供一些代码实现
这样正确吗?
public void update(UUID id,Long currentDate) {
UpdateQuery updateQuery = UpdateQuery.builder(id.toString()).withRouting("expirationDate=currentDate")
.build();
elasticsearchTemplate.bulkUpdate(List.of(updateQuery), IndexCoordinates.of("index"));
}
}
如果您使用的是 Elasticsearch 7.xx,我假设您使用的是 Spring Data Elasticsearch 版本 4。0.x 随 Spring boot 2.3.x。因为是支持Elasticsearch的版本7.xx.
此 Spring Data Elasticsearch 版本中有很多更改。通过查询更新文档就是其中之一。与之前我们自动装配 ElasticsearchTemplate 不同,我们现在必须改用 ElasticsearchRestTemplate 和 RestHighLevelClient。
在您的情况下,您可能希望使用 RestHighLevelClient 通过查询更新文档。假设您将 expirationDate 存储为以秒为单位的数字映射类型,那么您要求的代码应该如下所示。
public class ElasticsearchService {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Autowired
private RestHighLevelClient highLevelClient;
public void updateExpireDateDemo() throws IOException {
String indexName = "test";
Date currentDate = new Date();
Long seconds = (Long) (currentDate.getTime() / 1000);
UpdateByQueryRequest request = new UpdateByQueryRequest(indexName);
request.setQuery(new RangeQueryBuilder("expirationDate").lte(seconds));
Script updateScript = new Script(
ScriptType.INLINE, "painless",
"ctx._source.expirationDate=" + seconds + ";",
Collections.emptyMap());
request.setScript(updateScript);
highLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
}
}
我不太明白为什么您真的需要使用 bulkUpdate,但如果是这样的话。您必须首先从 Elasticsearch 查询需要更新的记录以获取每个文档的 ID。然后您可以使用 UpdateQuery 列表进行更新。所以您的代码将如下所示。
@Service
public class ElasticsearchService {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
public void updateExpireDateByBulkDemo() throws IOException {
String indexName = "test";
Date currentDate = new Date();
Long seconds = (Long) (currentDate.getTime() / 1000);
List<UpdateQuery> updateList = new ArrayList();
RangeQueryBuilder expireQuery = new RangeQueryBuilder("expirationDate").lte(seconds);
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(expireQuery).build();
SearchHits<Data> searchResult = elasticsearchRestTemplate.search(query, Data.class, IndexCoordinates.of(indexName));
for (SearchHit<Data> hit : searchResult.getSearchHits()) {
String elasticsearchDocumentId = hit.getId();
updateList.add(UpdateQuery.builder(elasticsearchDocumentId).withScript("ctx._source.expirationDate=" + seconds + ";").build());
}
if (updateList.size() > 0) {
elasticsearchRestTemplate.bulkUpdate(updateList, IndexCoordinates.of(indexName));
}
}
}
但是,这只会更新搜索结果的第一页。如果您需要更新与您的查询匹配的每条记录,那么您必须使用 searchScroll 方法来获取每个文档 ID。