Spring Data Elasticsearch (4.x) - 在 _source 中使用 @Id 强制 id 字段

Spring Data Elasticsearch (4.x) - Using @Id forces id field in _source

总结

最近我们升级到 Spring Data Elasticsearch 4.x。这个主要版本的一部分意味着 Jackson 不再用于将我们的域对象转换为 json(改为使用 MappingElasticsearchConverter)[1]。这意味着我们现在被迫向所有文档添加一个新的 id 字段。

以前我们有这样的域对象:

import org.springframework.data.annotation.Id;

public ESDocument {
    @Id
    private String id;

    private String field1;

    @JsonIgnore
    public String getId() {
        return id;
    }

    public String getField1() {
        return field1;
    }

这导致在 ES 中生成这样的文档:

{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "d5bf7b5c-7a44-42f9-94d6-d59fe3988482",
  "_score" : 1.0,
  "_source" : {
    "field1" : "blabla"
  }
}

注意:

  1. @JsonIgnore 注释用于确保我们不需要_source 中有一个 id 字段。
  2. 我们自己设置文档 ID,它最终在 _id

问题

使用 Spring Data Elastic 4.x 不再遵守 @JsonIgnore 注释,这意味着我们现在被迫在 [=19= 中有一个 id 字段] 如下图:

{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "d5bf7b5c-7a44-42f9-94d6-d59fe3988482",
  "_score" : 1.0,
  "_source" : {
    "id": "d5bf7b5c-7a44-42f9-94d6-d59fe3988482",
    "field1" : "blabla"
  }
}

问题

  1. 是否不再可以省略文档标识符的重复项(即在 _idid 字段中)?如果是这样怎么办? (请注意,我们已经尝试了 @org.springframework.data.annotation.Transient,但它不起作用,因为 spring-data-elastic 然后认为我们的文档没有 ID)。
  2. 我们之前在 _source 中抑制 id 字段的方法是不正确的还是有问题的?

版本

java: 1.8.0_252
弹性搜索:7.6.2
spring-引导:2.3.1.RELEASE
spring-数据弹性:4.0.1.RELEASE

参考资料

[1] - https://spring.io/blog/2020/05/27/what-s-new-in-spring-data-elasticsearch-4-0

问题一:

要从 _source 中省略 id 字段,您通常会使用 @Transient 注释,但如您所写,这不适用于 id 属性。 Spring 数据模块(不仅是 Spring Data Elasticsearch)忽略瞬态属性。

但是您可以为此使用 org.springframework.data.annotation.ReadOnlyProperty 注释:

@Id
@ReadOnlyProperty
private String id;

老实说,到现在为止我都不知道它存在,它也来自 Spring Data Commons,并在 [=53= 的 isWriteable() 方法中进行了检查] 当属性由 MappingElasticsearchConverter .

写入时

问题二:

当然没有错,但正如您所发现的那样有问题。我们在存储的时候总是考虑整个entity,所以从来没有想过不写id。严格来说,没有必要,你是对的,因为我们总是在 _id 字段中与 _source 一起获取 id,所以我们可以很容易地把实体放回原处,但我们从来没有认为这是一个必要的功能。

注:

当您查看 ES 索引中的数据时,您会发现 MappingElasticsearchConverter 一个额外的 _source 字段名为 _class 被写入其中包含实体的名称 class(或定义的别名)。这允许映射泛型;了解更多信息 check the documentation - 以防万一你想知道这是从哪里来的。