是否有一种优雅的方法来指定 Spring Data Elasticsearch 的 ObjectMapper 忽略的实体字段,同时让它们为 REST 序列化?

Is there an elegant way to specify entity's fields to ignore by Spring Data Elasticsearch's ObjectMapper while left them being serialized for 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);
    }

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

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

所以,我想让这个 ObjectMapper 只考虑上面带有 @Field 的字段,即只序列化标有 @Field 的字段并且不使用 @JsonView 人员.我该如何配置它?

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

此映射器仍需明确设置,3.2.0.RC2 的参考文档显示了如何执行此操作。使用此映射器,Jackson 注释不会影响 Elasticsearch 中存储和读取的数据。您可以在字段上使用 org.springframework.data.annotation.Transient 注释,使其不存储在 Elasticsearch 中。

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