【问题标题】: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?是否有一种优雅的方法来指定 Spring Data Elasticsearch ObjectMapper 忽略的实体字段,同时让它们为 REST 序列化?
【发布时间】:2023-03-12 23:52:01
【问题描述】:

换句话说,通用的 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 的序列化方式完全相同。并且 index 属性是动态创建的,使得资源被花费在大型二进制对象索引上。所以看起来@Field 用于启动时的初始索引创建,但未配置为与 Spring Data Elasticsearch 的 ObjectMapper 一起使用。

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

【问题讨论】:

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


    【解决方案1】:

    这些是在 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 自动映射。

    【讨论】:

    • 是的,我明白了。是否可以生成某种 java 注释或 Spring AOP 魔术来制作 1)现有的 @Field 注释被 Elasticsearch 的 ObjectMapper 解释为要处理的字段标记 2)至少创建自己的注释,该注释可以工作并接受 @987654325 @ 用于初始索引创建的参数,然后也与 Elasticsearch 的 ObjectMapper 的自定义 JsonView 的工作方式相同(当然不涉及 REST 序列化)。即在我的自定义代码中,而不是框架的代码中。
    • 对于@Transient,如果我希望 JPA 将此字段存储在数据库中,它对我不起作用。在我的用例中,我喜欢存储。
    猜你喜欢
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-20
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多