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

nwo49xxi  于 2022-11-22  发布在  ElasticSearch
关注(0)|答案(1)|浏览(138)

摘要

最近我们升级到了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字段。
    1.我们自己设置文档ID,结果是_id

问题

在Spring Data Elastic 4.x中,不再考虑@JsonIgnore注解,这意味着我们现在必须在_source中有一个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)。
1.我们之前在_source中抑制id字段的方法是否不正确或有问题?

个版本

Java语言版本:1.8.0_252
ElasticSearch:7.6.2
Spring Boot: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

n3schb8v

n3schb8v1#

问题1:

要省略 _source 中的id字段,通常需要使用@Transient注解,但正如您所写的,这对id属性不起作用。Spring Data 模块中会忽略 transient 属性(不仅仅是Spring Data Elasticsearch)。
但是您可以使用org.springframework.data.annotation.ReadOnlyProperty注解来实现:

@Id
@ReadOnlyProperty
private String id;

老实说,到目前为止我还不知道它的存在,它也来自Spring Data Commons,当MappingElasticsearchConverter编写属性时,在属性的isWriteable()方法中检查。

问题2:

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

备注:

当您查看ES索引中的数据时,您会发现MappingElasticsearchConverter中写入了一个名为 _class 的附加 _source 字段,其中包含实体类的名称(或定义的别名)。要了解更多的信息,请查看文档-以防万一你想知道这是从哪里来的。

2022年11月18日编辑:

最近(版本4.4.3)我们做了一个修改,修复了Spring Data Elasticsearch中的一个错误行为:Spring Data Elasticsearch不能将数据写入标记为@ReadOnlyProperty的属性。这会导致所建议的解决方案不再起作用,因为从Elasticsearch阅读数据时,id属性不再被填充。
要在这种情况下设置id属性,需要将AfterConvertCallback添加到应用程序中:

#import org.springframework.data.elasticsearch.core.event.AfterConvertCallback;

@Component
public class EntityAfterConvertCallback implements AfterConvertCallback<EsDocument> {

    @Override
    public EsDocument onAfterConvert(EsDocument entity, Document document, IndexCoordinates indexCoordinates) {
        entity.setId(document.getId());
        return entity;
    }
}

相关问题