'ElasticSearch - Spring Boot - Upsert is throwing DocumentMissingException
I am using Spring Boot and ElasticSearch. When I am trying to upsert using Spring, it is throwing DocumentMissingException
when there is no document present in the ElasticSearch. The same code works fine when there is a document present in the ElasticSearch.
Exception Stacktrace:
org.springframework.data.elasticsearch.ElasticsearchException: Bulk indexing has failures. Use ElasticsearchException.getFailedDocuments() for detailed messages [{U65929AR1978SGC001748=[company/vteSxfKoRF-k4g982vissw][[company][2]] DocumentMissingException[[_doc][U65929AR1978SGC001748]: document missing], U45309AR2000PTC006288=[company/vteSxfKoRF-k4g982vissw][[company][3]] DocumentMissingException[[_doc][U45309AR2000PTC006288]: document missing],...
Code:
public <S extends Company> void saveAllCustom(Iterable<S> companies) {
List<UpdateQuery> updateQueries = new ArrayList<UpdateQuery>();
ObjectMapper oMapper = new ObjectMapper();
for (S company : companies) {
Map<String, Object> companyJsonMap = (Map<String, Object>) oMapper.convertValue(company, Map.class);
Map<String, Object> paramsDocument = new HashMap<String, Object>();
paramsDocument.put("doc", companyJsonMap);
Script script = new Script(
ScriptType.INLINE
, "painless"
, "if (ctx._source.dataAsOf < params.doc.dataAsOf) {ctx._source = params.doc}"
, paramsDocument);
UpdateRequest updateRequest = new UpdateRequest()
.index("company")
.type("_doc")
.id(company.cin)
.script(script) // Conditional Update
.upsert(companyJsonMap);
UpdateQuery updateQuery = new UpdateQueryBuilder()
.withIndexName("company")
.withType("_doc")
.withId(company.cin)
.withDoUpsert(true)
.withClass(Company.class)
.withUpdateRequest(updateRequest)
.build();
updateQueries.add(updateQuery);
}
elasticsearchTemplate.bulkUpdate(updateQueries);
}
But a similar upsert command is working using CURL:
curl -X POST "localhost:9200/company/_doc/10001/_update" -H 'Content-Type: application/json' -d'
{
"script": {
"lang": "painless",
"source": "ctx._source = params.doc",
"params": {
"doc": {
"name": "XYZ LIMITED - updated",
"cin": "10001"
}
}
},
"upsert" : {
"name": "XYZ LIMITED - newly created",
"cin": "10001"
}
}'
As per my understanding, when there is no document present in the ElasticSearch, it shouldn't throw a DocumentMissingException
because I have added upsert(...)
as well in the query.
Elasticsearch version: Version: 6.4.3, Build: default/tar/fe40335/2018-10-30T23:17:19.084789Z, JVM: 1.8.0_191
Plugins installed: None
JVM version: java version "1.8.0_191" Java(TM) SE Runtime Environment (build 1.8.0_191-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
OS version: Darwin Kernel Version 18.5.0: Mon Mar 11 20:40:32 PDT 2019; root:xnu-4903.251.3~3/RELEASE_X86_64 x86_64
Spring Boot Version: 2.1.7.RELEASE
Spring Data ElasticSearch Version: 3.2.0.RC2
Solution 1:[1]
This is currently not supported by Spring Data Elasticsearch.
We can see it in the source code of ElasticsearchTemplate
that the upsert is not taken into account when a script is used.
Note that this issue has been reported, but it still hasn't been solved.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Val |