使用 Spring 引导从弹性搜索读取,其中 ES 记录没有 _class 属性

Reading from elastic search using Spring boot, where ES record without _class attribute

我正在尝试通过 Spring 数据 + Elastic read/search 弹性搜索中的现有记录 Search.The 弹性搜索中的现有记录没有 _class 属性。

 {  "_index": "status-000001",  
    "_type": "_doc",
    "_id": "demo",
    "_version": 1,
    "_score": null,
    "_source": {
    "Header.Type": "1",
    "Header.Version": "1.0.0",
    "Data.sample_rate": "10",
    "Data.upload_rate": "60",
    "Data.error_code": "0x00000000",
  },
}

当我查看映射规则的文档时,文档要求需要 _class。 https://docs.spring.io/spring-data/elasticsearch/docs/current-SNAPSHOT/reference/html/#elasticsearch.mapping.meta-model.rules

但此时,我们无法更新将数据引入 ES 的格式。

索引的映射

{
  "status-000001": {
    "mappings": {
      "properties": {
        "Data": {
          "properties": {
                "error_code": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "sample_rate": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "upload_rate": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                }          
            }
          }
        },
        "Header": {
          "properties": {
            "Type": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "Version": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        }
      }
    }
  }
}

对于如何处理这种情况,是否有任何建议?

这里的问题不是缺少 _class 条目。 Spring 数据 Elasticsearch 可以在没有这个的情况下读取实体(它是 在处理继承 类 和集合时确实需要)。

通常像这样的实体将是您所需要的(为简洁起见,我省略了 getter 和 setter):

@Document(indexName = "status")
public class Status {
    @Id
    private String id;

    @Field(name = "Header", type = FieldType.Object)
    private Header header;

    @Field(name = "Data", type = FieldType.Object)
    private Data data;

    static class Header {
        @Field(name = "Version", type = FieldType.Text)
        private String version;

        @Field(name = "Type", type = FieldType.Text)
        private String type;

    }

    static class Data {
        @Field(name = "error_code", type = FieldType.Text)
        private String errorCode;
        @Field(name = "sample_rate", type = FieldType.Text)
        private String sampleRate;
        @Field(name = "upload_rate", type = FieldType.Text)
        private String uploadRate;
    }

}

问题是您的 elasticsearch 文档具有点符号键中的对象结构:

{
    "Header.Type": "1",
    "Header.Version": "1.0.0",
    "Data.sample_rate": "10",
    "Data.upload_rate": "60",
    "Data.error_code": "0x00000000"
}

如果 _source 是 Spring Data Elasticsearch 就没有问题:

{
    "Header": {
        "Type": "1",
        "Version": "1.0.0"
    },
    "Data": {
        "sample_rate": "10",
        "upload_rate": "60",
        "error_code": "0x00000000"
    }
}

你可以做的是像这样编写一个自定义转换器(这里没有错误检查):

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.elasticsearch.core.document.Document;

import java.util.Map;

@ReadingConverter
public enum MapToStatusConverter implements Converter<Map<String, Object>, Status> {

    INSTANCE;

    @Override
    public Status convert(Map<String, Object> source) {

        if (source instanceof Document) {
            Document document = (Document) source;

            Status status = new Status();
            status.setId(document.getId());

            Status.Header header = new Status.Header();
            header.setType(document.getString("Header.Type"));
            header.setVersion(document.getString("Header.Version"));
            status.setHeader(header);

            Status.Data data = new Status.Data();
            data.setSampleRate(document.getString("Data.sample_rate"));
            data.setUploadRate(document.getString("Data.upload_rate"));
            data.setErrorCode(document.getString("Data.error_code"));
            status.setData(data);

            return status;
        }

        return null;
    }
}

此转换器需要在 configuring Spring Data Elasticsearch:

时注册
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {

        ClientConfiguration clientConfiguration = ClientConfiguration.builder() //
            .connectedTo("localhost:9200") //
            .build();

        return RestClients.create(clientConfiguration).rest();
    }

    @Override
    public ElasticsearchCustomConversions elasticsearchCustomConversions() {
        Collection<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(MapToStatusConverter.INSTANCE);
        return new ElasticsearchCustomConversions(converters);
    }
}

有了这个,您应该能够从 Elasticsearch 读取数据。