ES使用Java API创建映射报错:mapping source must be pairs offieldnames and properties definition.

ES使用Java API创建映射报错java.lang.IllegalArgumentException: mapping source must be pairs of fieldnames and properties definition.

原来代码如下:

String mapping = "{\n" +
                "      \"properties\" : {\n" +
                "        \"address\" : {\n" +
                "          \"type\" : \"text\",\n" +
                "          \"analyzer\" : \"ik_max_word\"\n" +
                "        },\n" +
                "        \"age\" : {\n" +
                "          \"type\" : \"long\"\n" +
                "        },\n" +
                "        \"name\" : {\n" +
                "          \"type\" : \"keyword\"\n" +
                "        }\n" +
                "      }\n" +
                "    }";
createIndexRequest.mapping(mapping, XContentType.JSON);

上述代码运行后会出现异常:

java.lang.IllegalArgumentException: 
mapping source must be pairs offieldnames and properties definition.

通过分析:
原因:导入过时包

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

底层:

    /**
     * A specialized simplified mapping source method, takes the form of simple properties definition:
     * ("field1", "type=string,store=true").
     */
    public CreateIndexRequest mapping(String type, Object... source) {
        mapping(type, PutMappingRequest.buildFromSimplifiedDef(type, source));
        return this;
    }

逐步进入方法:buildFromSimplifiedDef(type, source));

 /**
     * @param type
     *            the mapping type
     * @param source
     *            consisting of field/properties pairs (e.g. "field1",
     *            "type=string,store=true")
     * @throws IllegalArgumentException
     *             if the number of the source arguments is not divisible by two
     * @return the mappings definition
     */
    public static XContentBuilder buildFromSimplifiedDef(String type, Object... source) {
        if (source.length % 2 != 0) {
            throw new IllegalArgumentException("mapping source must be pairs of fieldnames and properties definition.");
        }

通过上述源码和相关注释文档可以看出第二个source参数是必须成对的,所以在上述代码中使用这个方法是缺少类型的也就是type。ES 7.x以后,将逐步移除type这个概念,现在的操作已经不再使用,默认为_doc。

public CreateIndexRequest mapping(String type, Object... source) {
    mapping(type, PutMappingRequest.buildFromSimplifiedDef(type, source));
    return this;
}

处理方法

应在mapping中添加"_doc"类型参数如下:

        String mapping = "{\n" +
                "      \"properties\" : {\n" +
                "        \"address\" : {\n" +
                "          \"type\" : \"text\",\n" +
                "          \"analyzer\" : \"ik_max_word\"\n" +
                "        },\n" +
                "        \"age\" : {\n" +
                "          \"type\" : \"long\"\n" +
                "        },\n" +
                "        \"name\" : {\n" +
                "          \"type\" : \"keyword\"\n" +
                "        }\n" +
                "      }\n" +
                "    }";
        createIndexRequest.mapping("_doc",mapping, XContentType.JSON);

底层方法如下:

   /**
     * Adds mapping that will be added when the index gets created.
     *
     * @param type   The mapping type
     * @param source The mapping source
     * @param xContentType The content type of the source
     */
    public CreateIndexRequest mapping(String type, String source, XContentType xContentType) {
        return mapping(type, new BytesArray(source), xContentType);
    }
这个错误通常出现在 Elasticsearch 的版本更新过程中,因为从 7.x 版本开始,默认情况下不再支持显式指定类型名称(即 `_doc`)。如果你尝试在未设置 `include_type_name=true` 参数的情况下向 Elasticsearch 发送包含类型的映射请求,则会遇到此问题。 ### 解决方案 #### 方法一:禁用类型名 最简单的方式是在构建 JSON 映射时不包括文档类型部分,直接针对索引本身操作即可。例如: ```json PUT /my_index { "mappings": { // 直接在这里定义字段属性等信息 "properties": { "field1": { "type": "text" } } } } ``` 可以看到我们去掉了原来的 `_doc` 层级结构,而将所有内容放置到根节点下的 mappings 中。 --- #### 方法二:启用 include_type_name 参数 如果确实需要保留旧版风格的 API 调用形式,在 URL 后添加查询字符串参数 `?include_type_name=true` 可以解决该问题。比如通过 Kibana Console 或 curl 命令行工具发送 HTTP 请求时像下面这样做: ```bash curl -X PUT "http://localhost:9200/my_index?include_type_name=true" -H 'Content-Type: application/json' -d' { "mappings": { "_doc": { "properties": { "field1": {"type": "keyword"} } } } }' ``` 注意这种方法仅作为临时过渡措施,并非推荐做法,未来更高级别的兼容可能会移除此类选项。 --- #### 方法三:降级至低版本Elasticsearch (不建议) 最后一种选择就是考虑回退使用较低版本的 Elasticsearch (如6.x系列),在那里依然允许自由地自定义各种数据类型及关联关系配置文件格式。但是这并不是一个长久之计,毕竟软件都会朝着更好的方向发展迭代升级,长期看还是应该适配新的标准规范较好!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值