ELK系列(4) - Elasticsearch cannot write xcontent for unknown value of type class java.math.BigDecimal

问题与分析

在使用Elasticsearch进行index数据时,发现报错如下:

java.lang.IllegalArgumentException: cannot write xcontent for unknown value of type class java.math.BigDecimal
	at org.elasticsearch.common.xcontent.XContentBuilder.unknownValue(XContentBuilder.java:755)
	at org.elasticsearch.common.xcontent.XContentBuilder.value(XContentBuilder.java:726)
	at org.elasticsearch.common.xcontent.XContentBuilder.field(XContentBuilder.java:711)
	at org.elasticsearch.index.query.BaseTermQueryBuilder.doXContent(BaseTermQueryBuilder.java:154)
	at org.elasticsearch.index.query.AbstractQueryBuilder.toXContent(AbstractQueryBuilder.java:82)
	at org.elasticsearch.index.query.BoolQueryBuilder.doXArrayContent(BoolQueryBuilder.java:275)
	at org.elasticsearch.index.query.BoolQueryBuilder.doXContent(BoolQueryBuilder.java:256)
	at org.elasticsearch.index.query.AbstractQueryBuilder.toXContent(AbstractQueryBuilder.java:82)
	at org.elasticsearch.common.xcontent.XContentBuilder.value(XContentBuilder.java:779)
	at org.elasticsearch.common.xcontent.XContentBuilder.value(XContentBuilder.java:772)
	at org.elasticsearch.common.xcontent.XContentBuilder.field(XContentBuilder.java:764)
	at org.elasticsearch.search.builder.SearchSourceBuilder.toXContent(SearchSourceBuilder.java:1184)
	at org.elasticsearch.common.xcontent.XContentHelper.toXContent(XContentHelper.java:349)
	at org.elasticsearch.search.builder.SearchSourceBuilder.toString(SearchSourceBuilder.java:1558)
	at org.elasticsearch.search.builder.SearchSourceBuilder.toString(SearchSourceBuilder.java:1553)
	at java.lang.String.valueOf(String.java:2994)
	at java.lang.StringBuilder.append(StringBuilder.java:131)
	at org.elasticsearch.action.search.SearchRequest.toString(SearchRequest.java:516)

从异常信息看,显然ES无法接受BigDecimal类型,经过百度,也确实如此。在一篇博文评论中解释如下:

应该是客户端代码里将查询的数值定义成了java.math.BigDecimal,而ES不支持这个类型。之所以2.2没有问题,是因为之前的transport client发送数据之前将其序列化成了json,而在5.x以后,使用的内部的transport protocol,数据类型如果不匹配会抛错误。

所以数据类型的定义上,需要使用ES支持的类型。

解决方案

方案一:转变成其他ES支持的数据类型

我使用的是6.4.2版本的Elasticsearch,该版本尚不支持BigDecimal或者BigInteger的数据类型,所以在index到Elasticsearch之前,需要转换成其他数据类型,这里要注意不要数据溢出了:

  1. BigDecimal要转变成Double类型
  2. BigInteger要转变成Long类型

方案二:使用更高版本的ES

我在看6.7.1版本的Elasticsearch源码时发现已经可以支持BigDecimal或者BigInteger的数据类型了,所以直接使用该版本或更高版本的就行了。

下面附上两个版本的支持的数据类型的源码:

  • 6.4.2版本的Elasticsearch相关源码
Map<Class<?>, Writer> writers = new HashMap<>();
writers.put(Boolean.class, (b, v) -> b.value((Boolean) v));
writers.put(Byte.class, (b, v) -> b.value((Byte) v));
writers.put(byte[].class, (b, v) -> b.value((byte[]) v));
writers.put(Date.class, XContentBuilder::timeValue);
writers.put(Double.class, (b, v) -> b.value((Double) v));
writers.put(double[].class, (b, v) -> b.values((double[]) v));
writers.put(Float.class, (b, v) -> b.value((Float) v));
writers.put(float[].class, (b, v) -> b.values((float[]) v));
writers.put(Integer.class, (b, v) -> b.value((Integer) v));
writers.put(int[].class, (b, v) -> b.values((int[]) v));
writers.put(Long.class, (b, v) -> b.value((Long) v));
writers.put(long[].class, (b, v) -> b.values((long[]) v));
writers.put(Short.class, (b, v) -> b.value((Short) v));
writers.put(short[].class, (b, v) -> b.values((short[]) v));
writers.put(String.class, (b, v) -> b.value((String) v));
writers.put(String[].class, (b, v) -> b.values((String[]) v));
writers.put(Locale.class, (b, v) -> b.value(v.toString()));
writers.put(Class.class, (b, v) -> b.value(v.toString()));
writers.put(ZonedDateTime.class, (b, v) -> b.value(v.toString()));
writers.put(Calendar.class, XContentBuilder::timeValue);
writers.put(GregorianCalendar.class, XContentBuilder::timeValue);
  • 6.7.1版本的Elasticsearch相关源码
Map<Class<?>, Writer> writers = new HashMap<>();
writers.put(Boolean.class, (b, v) -> b.value((Boolean) v));
writers.put(Byte.class, (b, v) -> b.value((Byte) v));
writers.put(byte[].class, (b, v) -> b.value((byte[]) v));
writers.put(Date.class, XContentBuilder::timeValue);
writers.put(Double.class, (b, v) -> b.value((Double) v));
writers.put(double[].class, (b, v) -> b.values((double[]) v));
writers.put(Float.class, (b, v) -> b.value((Float) v));
writers.put(float[].class, (b, v) -> b.values((float[]) v));
writers.put(Integer.class, (b, v) -> b.value((Integer) v));
writers.put(int[].class, (b, v) -> b.values((int[]) v));
writers.put(Long.class, (b, v) -> b.value((Long) v));
writers.put(long[].class, (b, v) -> b.values((long[]) v));
writers.put(Short.class, (b, v) -> b.value((Short) v));
writers.put(short[].class, (b, v) -> b.values((short[]) v));
writers.put(String.class, (b, v) -> b.value((String) v));
writers.put(String[].class, (b, v) -> b.values((String[]) v));
writers.put(Locale.class, (b, v) -> b.value(v.toString()));
writers.put(Class.class, (b, v) -> b.value(v.toString()));
writers.put(ZonedDateTime.class, (b, v) -> b.value(v.toString()));
writers.put(Calendar.class, XContentBuilder::timeValue);
writers.put(GregorianCalendar.class, XContentBuilder::timeValue);
writers.put(BigInteger.class, (b, v) -> b.value((BigInteger) v));
writers.put(BigDecimal.class, (b, v) -> b.value((BigDecimal) v));

可以发现,在6.7.1版本的源码里,多出了最后的两种数据类型的支持:BigInteger和BigDecimal。

参考链接

相关推荐
<div style="color:#444444;"> <strong>适用人群</strong> <p style="color:#666666;"> 开发从业人员,大数据从业人员,运维从业人员,IT相关从业人员,想快速掌握技能的一切人员 </p> </div> <p> <br /> </p> <strong>课程概述</strong> <p style="color:#666666;"> ElasticSearch7.x集群?Elasticsearch-head7.x官网都没有的插件整合?cerebro插件酷炫暗黑插件神器?一次搞定 </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <span style="font-size:18px;"><strong>官网版本</strong></span> </p> <p style="color:#666666;"> <img src="https://img-bss.csdn.net/201909191559264287.png" alt="" /> </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <span style="font-size:18px;">主从读写</span> </p> <p style="color:#666666;"> <span style="font-size:18px;"><img src="https://img-bss.csdn.net/201909191600534277.png" alt="" /><br /> </span> </p> <p style="color:#666666;"> <span style="font-size:18px;"><strong>中文分词</strong></span> </p> <p style="color:#666666;"> <img src="https://img-bss.csdn.net/201909191558496304.png" alt="" /> </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> Head插件 </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <img src="https://img-bss.csdn.net/201909191601265587.png" alt="" /> </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <span> </span> </p> <div style="font-size:14pt;"> <span style="font-size:18px;">cerebro插件</span> </div> <img src="https://img-bss.csdn.net/201909191601542208.png" alt="" />
<p> <span style="font-size:18px;">版本定位:</span> </p> <p> <span style="font-size:18px;">目前采用ELK7.x:即ELKelasticsearch7.3+logstash7.3+kibana7.3)</span> </p> <span style="font-size:18px;">官网最新版本搭建集群和展示</span><br /> <p> <span style="font-size:18px;"></span> </p> <p> <span style="font-size:18px;"><strong>elk是什么意思中文?</strong></span> </p> <p> <span style="color:#333333;">ELK Stack 是Elasticsearch、Logstash、Kiban三个开源软件的组合。在实时数据检索和分析场合,三者通常是配合共用,而且又都先后归于 Elastic.co 公司名下,故有此简称。 ELK Stack成为机器数据分析,或者说实时日志处理领域,开源界的第一选择。和传统的日志处理方案相比,ELK Stack 具有如下几个优点: • 处理方式灵活。Elasticsearch 是实时全文索引,不需要像 storm 那样预先编程才能使用; • 配置简易上手。Elasticsearch 全部采用 JSON 接口,Logstash 是 Ruby DSL 设计,都是目前业界最通用的配置语法设计; • 检索性能高效。虽然每次查询都是实时计算,但是优秀的设计和实现基本可以达到全天数据查询的秒级响应; • 集群线性扩展。不管是 Elasticsearch 集群还是 Logstash 集群都是可以线性扩展的; • 前端操作炫丽。Kibana 界面上,只需要点击鼠标,就可以完成搜索、聚合功能,生成炫丽的仪表板。 官网地址:https://www.elastic.co/cn/</span> </p> <p> <strong><span style="font-size:18px;">elk日志分析系统?</span></strong> </p> <p> ELK+Beats日志分析系统部署,<span style="color:#333333;">Elasticsearch分布式集群部署,加上ELK Stack堆栈,让搜索发挥极致</span> </p> <p> <br /> </p>
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页