Hello, ES team!
There is a precision losing problem when I'm using java client of ElasticSearch.
Will you fix this bug recently? We do need a big decimal in developing financial system.
Thanks very much!
[Development Environment]
JDK: 1.8
ElasticSearch Server Version: 6.4.2 / 6.8.9 / 7.9.0
ElasticSearch Client Version: 6.4.2 / 6.8.9 / 7.9.0
[Mapping]
PUT test_idx/_doc/_mapping
{
"properties": {
"balance":{"type": "double"}
}
}
[Main Codes & Results -- version of java client and ES server: 6.4.2 / 6.8.9]
BigDecimal val = new BigDecimal("12345678901234567890.12345");
JSONObject jsonObject = new JSONObject();
jsonObject.put("balance", val);
/* Single Put */
// The field 'balance' in curl result by shell showed the correct value '12345678901234567890.12345'
client.index(new IndexRequest("test_idx", "_doc", "1").source(jsonObject.toJSONString(), XContentType.JSON)
,RequestOptions.DEFAULT);
/* Bulk Load */
// The field 'balance' in curl result by shell showed the precision losing value '1.2345678901234567E19'
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new IndexRequest("test_idx", "_doc", "2").source(jsonObject.toJSONString(), XContentType.JSON));
client.bulk(bulkRequest, RequestOptions.DEFAULT);
[Main Codes & Results -- version of java client and ES server: 7.9.0]
BigDecimal val = new BigDecimal("12345678901234567890.12345");
JSONObject jsonObject = new JSONObject();
jsonObject.put("balance", val);
/* Single Put */
// The field 'balance' in curl result by shell showed the correct value '12345678901234567890.12345'
client.index(new IndexRequest("test_idx").source(jsonObject.toJSONString(), XContentType.JSON)
,RequestOptions.DEFAULT);
/* Bulk Load */
// The field 'balance' in curl result by shell showed the precision losing value '1.2345678901234567E19'
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new IndexRequest("test_idx").source(jsonObject.toJSONString(), XContentType.JSON));
client.bulk(bulkRequest, RequestOptions.DEFAULT);
[Debug and Modify code in java client of ES 7.9.0]
From the results above in different version we can see that it'll losing precision when bulk loading data into ES.
So I debugged code, and I found this bug occured in function '_parseSlowFloat(int expType)' of class 'jackon-core-2.10.4.jar/com.fasterxml.jackson.core.base.ParserBase', the value of variable 'expType' is always 0(int value) from begging, it havn't changged, so the non-int numeric value will be regarded as type 'double' always.
And then, I done these:
[1] downloaded the source code 'jackson-core-2.10.4-sources.jar' and decompressed it into my project.
[2] altered code
/********* before /
if (expType == NR_BIGDECIMAL) {
_numberBigDecimal = _textBuffer.contentsAsDecimal();
_numTypesValid = NR_BIGDECIMAL;
} else {
// Otherwise double has to do
_numberDouble = _textBuffer.contentsAsDouble();
_numTypesValid = NR_DOUBLE;
}
/ after *********/
_numberBigDecimal = _textBuffer.contentsAsDecimal();
_numTypesValid = NR_BIGDECIMAL;
[3] rerun bulk load code to ES, field 'balance' in curl result by shell showed the correct value '12345678901234567890.12345'