【问题标题】:Reading from elastic search using Spring boot, where ES record without _class attribute使用 Spring boot 从弹性搜索中读取,其中 ES 记录没有 _class 属性
【发布时间】:2021-03-15 12:03:07
【问题描述】:

我正在尝试通过 Spring Data + Elastic Search 读取/搜索 Elastic Search 中的现有记录。弹性搜索中的现有记录没有 _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 Data Elasticsearch 可以在没有它的情况下读取它(在处理通用数据时确实需要它)。这条记录在 Elasticsearch 中的映射是什么(GET /status-000001/_mappings)?
  • @P.J.Meisch,我已经用索引的 ES 映射更新了这个问题。我正在使用 SearchHits result = elasticsearchOperations.search(query, Status.class, IndexCoordinates.of("status-000001")); Status.class 表示 ES 记录的 POJO。

标签: spring-boot spring-data spring-data-elasticsearch


【解决方案1】:

这里的问题不是缺少_class 条目。 Spring Data 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;
    }

}

问题在于您的弹性搜索文档在点符号键中具有对象结构:

{
    "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 读取数据了。

【讨论】:

    猜你喜欢
    • 2018-06-08
    • 2014-11-04
    • 1970-01-01
    • 2020-10-22
    • 2014-10-17
    • 2017-05-12
    • 2016-08-22
    • 1970-01-01
    相关资源
    最近更新 更多