Skip to content
欢迎扫码关注公众号

Elasticsearch MapperParsingException

使用 Java API 添加第一条索引记录时,如果 Elasticsearch 中还没有该索引则会自动创建该索引。

今天遇到一个奇怪的情况,有一条数据,通过该数据创建索引时有异常,通过别的数据则没有该错误。

最奇怪的是一旦通过正常的数据创建成功后,之前错误的数据也能正常插入了。

txt
MapperParsingException[failed to parse]; nested: IllegalArgumentException[mapper [priceDetails.amountSettlement] of different type, current_type [double], merged_type [long]];

数据库中该字段为 decimal(18, 2),Model 中为 BigDecimal

具体的数据 (Json 格式) 为:

json
{
    "priceDetails": [
        {
            "amountSettlement": -0.1,
            "amountSupplier": 0,
            "amountType": 2,
            "guid": "E382F203-71FE-4365-8332-0D430FE961DA",
            "payType": 4,
            "wholeGroupDemandGuid": "DE937A24-3E65-4B8B-A273-0833FB2CC5EC"
        },
        {
            "amountSettlement": 100,
            "amountSupplier": 100,
            "amountType": 1,
            "guid": "12E36173-9346-406F-BC98-24D92391CDFE",
            "payType": 1,
            "wholeGroupDemandGuid": "DE937A24-3E65-4B8B-A273-0833FB2CC5EC"
        },
        {
            "amountSettlement": 0,
            "amountSupplier": -1,
            "amountType": 3,
            "guid": "F1955B5E-99CD-4939-8396-6E740A05A52E",
            "payType": 5,
            "wholeGroupDemandGuid": "DE937A24-3E65-4B8B-A273-0833FB2CC5EC"
        },
        {
            "amountSettlement": 0,
            "amountSupplier": 0,
            "amountType": 2,
            "guid": "A32048B5-D78D-483E-8A29-C55EACD078DA",
            "payType": 6,
            "wholeGroupDemandGuid": "DE937A24-3E65-4B8B-A273-0833FB2CC5EC"
        }
    ]
}

通过尝试发现在该值为带小数点的值时,创建索引会出异常。

猜测原因应该是还未创建索引类型时需要确定该属性的类型;

第一行带小数点被认为是 double 型;

第二行不带小数点被认为是 long 型;

导致两行的字段类型不一致,于是报错。


Elasticsearch 的坑爹事——记录一次 mapping field 修改过程

ElasticSearch 的索引一旦创建后不允许修改 field 的类型。

只能创建一个新索引,然后同步旧的索引数据到新索引。


net.sf.json.JsonConfig 使用详解

自定义 Json 格式


暂时的解决方案: 使用 JsonBeanProcessorBigDecimal 转成 String 型格式,在搜索引擎中字段为 String 型。

注意

这种方案会导致数值大小之类的比较变成字符串大小的比较。

代码:

java
package com.octopus.core;

import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * Created by liujiajia on 2016/11/8.
 */
public class JsonBigDecimalValueProcessor implements JsonValueProcessor {
    private String format = "0.00";

    public JsonBigDecimalValueProcessor() {
        super();
    }

    public JsonBigDecimalValueProcessor(String format) {
        super();
        this.format = format;
    }

    @Override
    public Object processArrayValue(Object o, JsonConfig jsonConfig) {
        return process(o);
    }

    @Override
    public Object processObjectValue(String s, Object o, JsonConfig jsonConfig) {
        return process(o);
    }

    private Object process(Object value) {
        if (value instanceof BigDecimal) {
        // return ((BigDecimal) value).doubleValue();
            DecimalFormat df = new DecimalFormat(format);
            return df.format(value);
        }
        return value == null ? "0" : value.toString();
    }
}

调用:

java
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.registerJsonValueProcessor(BigDecimal.class, new JsonBigDecimalValueProcessor());
return JSONObject.fromObject(object, jsonConfig).toString();

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.