首页 > 解决方案 > 有没有一种优雅的方法来指定要被 Spring Data Elasticsearch 的 ObjectMapper 忽略的实体字段,同时让它们为 REST 序列化?

问题描述

换句话说,普通的 Jackson 标记不足以序列化相同的实体以用作 Angular 前端的 REST 请求响应,并通过 Jest 客户端将对象传递给 Elasticsearch。说,我在实体中有一个图像作为字节数组,我希望将它存储到数据库并传递到前端,但不希望它被 Elasticsearch 索引以降低成本或配额。

现在我必须使用 Jackson 的 JsonView 来标记要用于 Spring Data Elasticsearch 的 ObjectMapper 的字段:

@Entity
@Table(name = "good")
@org.springframework.data.elasticsearch.annotations.Document(indexName = "good", shards = 1, replicas = 0, refreshInterval = "-1")
public class Good implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
@org.springframework.data.elasticsearch.annotations.Field(type = FieldType.Keyword)
@JsonView(Views.Elasticsearch.class)
private Long id;

@NotNull
@Column(name = "short_name", nullable = false)
@JsonView(Views.Elasticsearch.class)
@Field(store = true, index = true, type=FieldType.Text)
private String shortName;

@NotNull
@Column(name = "description", nullable = false)
@JsonView(Views.Elasticsearch.class)
@Field(store = true, index = true, type=FieldType.Text)
private String description;


@Lob
@Column(name = "image", nullable = false)
@JsonView(Views.Rest.class)
private byte[] image;

@Column(name = "image_content_type", nullable = false)
@JsonView(Views.Rest.class)
private String imageContentType;

@NotNull
@Column(name = "price", nullable = false)
@JsonView(Views.Elasticsearch.class)
@Field(store = true, index = true, type=FieldType.Integer)
private Integer price;
...

我有一堂课Views

public class Views {
public static class Rest{}
public static class Elasticsearch{}
}

并且在对应的Bean中设置了ObjectMapper:

    @Override
    public String mapToString(Object object) throws IOException {
        log.trace("Object to convert to JSON : {}",object);
        log.trace("Converting to json for elasticsearch >>> {}",objectMapper.writer().withView(Views.Elasticsearch.class).writeValueAsString(object));
        //log.trace("Converting to json for elasticsearch >>> {}",objectMapper.writeValueAsString(object));
        return objectMapper.writerWithView(Views.Elasticsearch.class).writeValueAsString(object);
        //return objectMapper.writeValueAsString(object);
    }

因此,我必须标记除忽略 Elasticsearch 之外的所有字段 @JsonView(Views.Elasticsearch.class),这很容易出错。@Field此外,如果我想在那里传递一些参数,这个字段仍然需要使用store值类型当我有@JsonView(Views.Elasticsearch.class),但没有@Field一些时,这些字段是在索引中动态创建的,这允许它们搜索,但不是以所需的方式。

最新的原因是如果我只是将@Field 留在那里并且不将它放在我不想索引到 Elasticsearch 中的字段上,初始索引确实会忽略它们,但是当实体被序列化时,稍后的请求会传递不需要的字段与为 REST 完成的方式完全相同。并且 index 属性是动态创建的,使得资源被用于大型二进制对象索引。所以看起来像@Field用于启动时的初始索引创建,但未配置为与 Spring Data Elasticsearch 的 ObjectMapper 一起使用。

所以,我想让这个 ObjectMapper 只考虑@Field上面的字段,即序列化标记为@Fieldonly 而不使用@JsonView人员的字段。我该如何配置它?

标签: spring-bootelasticsearchjacksonspring-dataspring-data-elasticsearch

解决方案


这些是在 Spring Data Elasticsearch 中使用 Jackson Object Mapper 时的已知问题(这也是默认设置),这也是为什么在 Spring Data Elasticsearch 3.2 版(目前在 RC2 中并将作为 3.2 版)中的原因之一.0.GA 在 9 月中旬),有一个不同的映射器可用,ElasticsearchEntityMapper.

这个映射器仍然必须明确设置,3.2.0.RC2 的参考文档显示了如何做到这一点。使用此映射器,Jackson 注释不会影响 Elasticsearch 中存储和读取的数据。您可以使用org.springframework.data.annotation.Transient字段上的注释使其不存储在 Elasticsearch 中。

@Field注解用于设置初始 Elasticsearch 映射,没有此注解的属性在插入时由 Elasticsearch 自动映射。


推荐阅读