【问题标题】:neo4j java node dynamic propertiesneo4j java节点动态属性
【发布时间】:2016-06-30 11:38:01
【问题描述】:

我正在尝试创建具有可以是动态属性的特定类型的节点。 例如:我可以创建一个具有 name、age、address 属性的 Person 节点。但是当我创建另一个 Person 节点时,这些不一定是唯一的属性。这个节点可以有姓名、年龄、地址和额外的财产工资。使用 Spring Data 或查询 DSL 需要我创建具有固定数量的实例变量 name、age 和 address 的 Java POJO 类 Person。

@NodeEntity
public class Person {
@GraphId private Long id;

private String name;
private String age;
private String address;
}

我无法为另一个 Person 节点添加薪金的动态属性。有什么方法可以实现吗?

【问题讨论】:

  • 但是属性是可选的,你不必设置它们。

标签: neo4j querydsl spring-data-neo4j-4 neo4j-ogm


【解决方案1】:

目前 Neo4j-OGM 不支持动态属性(请参阅https://jira.spring.io/browse/DATAGRAPH-555

如果您仅通过 OGM 与您的图表交互并且不必查询单个动态属性,您可以尝试使用自定义转换器的属性映射,该转换器将此映射转换为字符串(如 json)。然后,OGM 将使用此转换器将映射序列化到图形和从图形中导出。 请注意,由于这些值被压缩为字符串,因此现在查询单个动态属性并非易事。

要创建custom converter,您需要实现org.neo4j.ogm.typeconversion.AttributeConverter 并提供从Map 转换为String 的实现。 然后,像这样在您的域实体中注释您的地图属性:

 @Convert(MoneyConverter.class)

编辑:

正如 Michael 所指出的,如果薪水是唯一额外的可选属性,那么拥有这个属性是有意义的,但只有在它有值时才设置它。在这种情况下,动态属性是多余的。当您有一组未知且任意的属性要与节点持久保存时,您可能希望使用动态属性

【讨论】:

  • 感谢您的回答。你能指点我这个自定义转换器的例子吗?
  • 非常感谢。让我试试这个。实际上,我引用的示例仅将薪水作为一个额外字段,但实际用例确实具有未知且任意的属性集。
【解决方案2】:

您可以通过创建CompositeAttributeConverter 来解决这些限制,将每个动态属性保存在图中(不仅因为 JSON-String 无法很好地查询 - 正如 luanne 在接受的答案中提到的那样)

import java.lang.reflect.Field;
import java.util.*;

import org.neo4j.ogm.typeconversion.CompositeAttributeConverter;

public abstract class DynamicPropertiesConverter implements CompositeAttributeConverter<Map<String, ?>> {

    private Set<String> blacklist;

    public DynamicPropertiesConverter(Class<?> clazz) {
        blacklist = new HashSet<>();
        addAllFields(clazz);
    }
    public DynamicPropertiesConverter(Set<String> blacklist) {
        this.blacklist = blacklist;
    }

    public void addAllFields(Class<?> type) {
        for (Field field : type.getDeclaredFields()) {
            blacklist.add(field.getName());
        }
        if (type.getSuperclass() != null) {
            addAllFields(type.getSuperclass());
        }
    }

    @Override
    public Map<String, ?> toGraphProperties(Map<String, ?> value) {
        Map<String, ?> result = new HashMap<>(value);
        result.keySet().removeAll(blacklist);
        return result;
    }

    @Override
    public Map<String, ?> toEntityAttribute(Map<String, ?> value) {
        return toGraphProperties(value);
    }
}

现在您可以创建此转换器的特殊版本:

public class DynamicNodePropertiesConverter extends DynamicPropertiesConverter {
    public DynamicNodePropertiesConverter() {
        super(Node.class);
    }
}

并像这样使用它:

import java.util.Map;

import DynamicNodePropertiesConverter;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import org.neo4j.ogm.annotation.typeconversion.Convert;

@NodeEntity
public class Node {

    @Convert(DynamicNodePropertiesConverter.class)
    private Map<String, Object> data;

    /* getter and setter */
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多