【问题标题】:Reusing a single entity between Spring Data Neo4J and Elasticsearch在 Spring Data Neo4J 和 Elasticsearch 之间重用单个实体
【发布时间】:2019-12-02 23:23:27
【问题描述】:

我正在使用 Spring Boot 2.2.1、Spring Data Neo4J 和 Spring Data Elasticsearch 来构建基于图形的应用程序。对于图表,我有一个实体类,它有一个 @Relationship 字段来存储一组相关实体。对于实体搜索,我想使用 Elasticsearch。我已将 ElasticSearch 注释添加到同一实体,禁用 Elasticsearch 自动配置并配置 Neo4J 和 Elasticsearch 存储库配置。

应用程序正确启动,但是当我尝试将实体保存到 Elasticsearch 时,由于关系属性,我收到了 stackoverflow 错误。我试过了:

  1. 使用 @JsonIgnoreProperties 注释从 Elasticsearch 中排除该字段。
  2. 使用@Field(ignoreFields = {"fieldName"}) 注释字段

但我得到了同样的错误。

如何排除写入 Elasticsearch 的字段?

实体定义:

实体:

package test.model;

import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Properties;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.Relationship;
import org.neo4j.ogm.annotation.typeconversion.Convert;
import org.neo4j.ogm.id.UuidStrategy;
import org.neo4j.ogm.typeconversion.UuidStringConverter;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.Mapping;
import org.springframework.data.elasticsearch.annotations.Setting;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.neo4j.ogm.annotation.GeneratedValue;

@NodeEntity
@Document(indexName = "entities")
@Mapping(mappingPath = "/mappings/mappings.json")
@Setting(settingPath = "/settings/settings.json")
public class Entity {

    @org.neo4j.ogm.annotation.Id
    @org.springframework.data.annotation.Id
    @GeneratedValue(strategy = UuidStrategy.class)
    @Convert(UuidStringConverter.class)
    @Property("uuid")
    private UUID id;

    @Field(type = FieldType.Keyword)
    private String name;

    private String description;

    private String type;

    private Long count;

    @Field(type = FieldType.Keyword)
    private String[] aliases;

    private String[] socialLinks;

    @Properties
    private Map<String, Object> attributes;

    private String image;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    private Date creationDate;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    private Date lastModifiedDate;

    @Relationship(type = RelatedEntity.TYPE, direction = Relationship.UNDIRECTED)
    private Set<RelatedEntity> relatedEntities = new HashSet<>();

    public Map<String, Object> getAttributes() {
        return attributes;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public String[] getSocialLinks() {
        return socialLinks;
    }

    public void setSocialLinks(String[] socialLinks) {
        this.socialLinks = socialLinks;
    }

    public String[] getAliases() {
        return aliases;
    }

    public void setAliases(String[] aliases) {
        this.aliases = aliases;
    }

    public UUID getId() {
        return id;
    }

    public void setId(UUID id) {
        this.id = id;
    }

    public void setAttributes(Map<String, Object> attributes) {
        this.attributes = attributes;
    }

    public Date getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(Date lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public Long getCount() {
        return count;
    }

    public void setCount(Long count) {
        this.count = count;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<RelatedEntity> getRelatedEntities() {
        return relatedEntities;
    }

    public void setRelatedEntities(Set<RelatedEntity> relatedEntities) {
        this.relatedEntities = relatedEntities;
    }
}

相关实体:

package test.mode;

import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;

@RelationshipEntity(type = RelatedEntity.TYPE)
public class RelatedEntity {

    public static final String TYPE = "RELATED_TO";

    @Id
    @GeneratedValue
    private Long id;

    @StartNode
    private Entity start;

    @EndNode
    private Entity end;

    @Property
    private Long count;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getCount() {
        return count;
    }

    public void setCount(Long count) {
        this.count = count;
    }

    public Entity getEnd() {
        return end;
    }

    public void setEnd(Entity end) {
        this.end = end;
    }

    public Entity getStart() {
        return start;
    }

    public void setStart(Entity start) {
        this.start = start;
    }
}

【问题讨论】:

  • 您能否展示您的实体类的完整定义?您为 Elasticsearch 使用哪个客户端?交通还是休息?
  • 添加了上面的实体定义。我正在使用 REST 客户端连接到 Elasticsearch。

标签: spring-data-neo4j spring-data-elasticsearch


【解决方案1】:

我强烈建议不要使用相同的实体将其存储在不同的数据存储中。这真的很麻烦,因为字段和注释可能会有不同的解释。为不同的商店定义不同的类型,并提供从一个到另一个映射的代码。

我不知道您使用哪个 Mapper 将您的实体映射到 Elasticsearch 文档。当您使用 Spring Boot 2.2.1 时,可能是使用 Jackson 的 DefaultEntityMapper。由于这会导致很多问题(通过在类上重用 Jackson 注释用于不同目的,例如存储到不同的数据存储或通过 REST API 传递值),我们决定在即将发布的版本中删除基于 Jackson 的映射器,只使用 @987654321 @。这尊重了类上定义的所有@Field 注释值,而基于 Jackson 的映射器并非如此。

所以我建议为不同的数据存储重写你的实体类,使用ElasticsearchEntityMapper 并检查@Field 注释的不同属性来定义你的类的属性。

【讨论】:

  • 好的,谢谢。在另一个应用程序中,我能够为 MongoDB 和 Elasticsearch 使用相同的实体而没有任何问题,但我明白你的意思。我现在将创建两个实体类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-11
  • 2020-04-12
相关资源
最近更新 更多