You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OpenSearch Java客户端创建索引时遇未知配置错误求助

问题:OpenSearch Java客户端创建索引时出现未知配置错误

索引配置JSON

{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "my_synonym_analyzer": {
            "type": "custom",
            "tokenizer": "whitespace",
            "filter": [
              "my_synonym_filter"
            ]
          }
        },
        "filter": {
          "my_synonym_filter": {
            "type": "synonym_graph",
            "synonyms": []
          }
        }
      }
    }
  }
}

Java创建索引代码

import jakarta.json.stream.JsonParser;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.opensearch.client.json.JsonpMapper;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.opensearch._types.mapping.TypeMapping;
import org.opensearch.client.opensearch.indices.CreateIndexRequest;
import org.opensearch.client.opensearch.indices.CreateIndexResponse;
import org.opensearch.client.opensearch.indices.IndexSettings;
import org.opensearch.common.io.Streams;
import org.springframework.beans.factory.annotation.Autowired;

public class IndexManager {

  @Autowired private OpenSearchClient searchClient;

  protected void create() throws IOException {

    if (this.indexExists()) {
      this.delete();
    }

    JsonpMapper mapper = searchClient._transport().jsonpMapper();
    try (Reader readerSettings =
            new InputStreamReader(
                Objects.requireNonNull(
                    this.getClass()
                        .getResourceAsStream("testindex-index-settings.json")));
        Reader readerMappings =
            new InputStreamReader(
                Objects.requireNonNull(
                    this.getClass()
                        .getResourceAsStream("testindex-index-mappings.json")));
        JsonParser settingsParser =
            mapper
                .jsonProvider()
                .createParser(new StringReader(Streams.copyToString(readerSettings)));
        JsonParser mappingsParser =
            mapper
                .jsonProvider()
                .createParser(new StringReader(Streams.copyToString(readerMappings))); ) {

      String indexName = "testindex";

      IndexSettings indexSettings = IndexSettings._DESERIALIZER.deserialize(settingsParser, mapper);

      TypeMapping typeMapping = TypeMapping._DESERIALIZER.deserialize(mappingsParser, mapper);

      CreateIndexRequest indexRequest =
          new CreateIndexRequest.Builder()
              .index(indexName)
              .settings(indexSettings)
              .mappings(typeMapping)
              .build();

      CreateIndexResponse indexResponse = searchClient.indices().create(indexRequest); // line 93

      log.info("Index {} created with response [{}]", indexName, indexResponse.toString());
    }
  }
}

报错信息

org.opensearch.client.opensearch._types.OpenSearchException: Request failed: [illegal_argument_exception] unknown setting [index.settings.analysis.analyzer.my_synonym_analyzer.filter] please check that any required plugins are installed, or check the breaking changes documentation for removed settings
    at org.opensearch.client.transport.rest_client.RestClientTransport.getHighLevelResponse(RestClientTransport.java:273) ~[opensearch-java-2.4.0.jar:na]
    at org.opensearch.client.transport.rest_client.RestClientTransport.performRequest(RestClientTransport.java:143) ~[opensearch-java-2.4.0.jar:na]
    at org.opensearch.client.opensearch.indices.OpenSearchIndicesClient.create(OpenSearchIndicesClient.java:248) ~[opensearch-java-2.4.0.jar:na]
    at com.joinhobnob.crm.service.search.command.IndexManager.create(IndexManager.java:93) ~[main/:na]

curl创建成功案例

curl -XPUT "http://opensearch:9200/test_index?pretty" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "my_synonym_analyzer": {
            "type": "custom",
            "tokenizer": "whitespace",
            "filter": [
              "my_synonym_filter"
            ]
          }
        },
        "filter": {
          "my_synonym_filter": {
            "type": "synonym_graph",
            "synonyms": []
          }
        }
      }
    }
  }
}'

响应:

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "test_index"
}

解决方案

问题根源在于Java客户端的IndexSettings类反序列化逻辑:它对应OpenSearch索引配置中index.settings层级的内容,但你的JSON配置把analysis放在了settings.index下,反序列化后导致发送给OpenSearch的请求多嵌套了一层settings,路径变成index.settings.analysis...,而OpenSearch期望的是index.analysis...,因此抛出未知配置错误。

提供两种解决方式:

方式一:修改JSON配置文件

移除JSON中多余的index层级,让analysis直接放在settings下:

{
  "analysis": {
    "analyzer": {
      "my_synonym_analyzer": {
        "type": "custom",
        "tokenizer": "whitespace",
        "filter": [
          "my_synonym_filter"
        ]
      }
    },
    "filter": {
      "my_synonym_filter": {
        "type": "synonym_graph",
        "synonyms": []
      }
    }
  }
}

这样IndexSettings反序列化后就能正确匹配OpenSearch的配置结构。

方式二:直接使用JSON字符串构建请求

绕开IndexSettings和TypeMapping的反序列化,直接将配置文件内容以字符串形式传入请求,和curl发送的内容保持完全一致:
修改Java代码中的请求构建部分:

// 读取配置文件为字符串
String settingsStr = Streams.copyToString(readerSettings);
String mappingsStr = Streams.copyToString(readerMappings);

String indexName = "testindex";

CreateIndexRequest indexRequest = new CreateIndexRequest.Builder()
    .index(indexName)
    .settings(settingsStr, JsonpMapper.DEFAULT) // 直接传入JSON字符串
    .mappings(mappingsStr, JsonpMapper.DEFAULT)
    .build();

CreateIndexResponse indexResponse = searchClient.indices().create(indexRequest);

这种方式不需要修改原JSON配置,直接复用现有文件即可。


内容的提问来源于stack exchange,提问作者Sabu Shakya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 11:05:00