将相同类型的节点与SDN相关联

时间:2016-07-05 13:08:21

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

我正在使用Spring Data Neo4j 4。 假设我有类型为Person的节点,并且相应的Java域对象是

 @NodeEntity
 public class Person {

     @GraphId private Long id;

     private String name;

     private String lastName;

     @Relationship(type = "KNOWS")
     Set<Person> myTypes;


 }

我正在尝试创建一个像`

这样的图表
  

John-KNOWS-&gt; George和John-KNOWS-&gt; Ann。安 - KNOWS-&GT;挖

`。以下是我如何设置域对象并保持持久性。

    Person john = new Person("John","P");
    Person george = new Person("George","B");
    Person Ann = new Person("Ann","M");
    Person Dug = new Person("Dug","S");
    Set<Person> Persons= new HashSet<Person>();
    Set<Person> Persons1= new HashSet<Person>();
    Persons1.add(Dug);
    Ann.setMyTypes(Persons1);
    Persons.add(george);
    Persons.add(Ann);
    john.setMyTypes(Persons);

    personRepository.save(john);
    personRepository.save(george);
    personRepository.save(Ann);
    personRepository.save(Dug);

但令我惊讶的是,只创建了没有关系的节点。我正在调试这个并在此行之后        personRepository.save(约翰) 已创建具有关系的节点,但在后续保存期间,所有关系都已删除。 下面是日志中打印的内容,并清楚地表明关系已被删除。

 Request: UNWIND {rows} as row CREATE (n:`Person`) SET n=row.props RETURN   row.nodeRef as ref, ID(n) as id, row.type as type with params {rows=[{nodeRef=-2115049587, type=node, props={name=George, attrib=B}}, {nodeRef=-341599918, type=node, props={name=Ann, attrib=M}}, {nodeRef=-737678933, type=node, props={name=John, attrib=P}}, {nodeRef=-1025122203, type=node, props={name=Dug, attrib=S}}]}
 Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MERGE (startNode)-[rel:`KNOWS`]->(endNode) RETURN row.relRef as ref, ID(rel) as id, row.type as type with params {rows=[{relRef=-1807300324, endNodeId=2448, type=rel, startNodeId=2450}, {relRef=-272508006, endNodeId=2451, type=rel, startNodeId=2449}, {relRef=-845107952, endNodeId=2449, type=rel, startNodeId=2450}]}
 Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2448, startNodeId=2450}]}
 Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2449, startNodeId=2450}]}
 Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2451, startNodeId=2449}]}

不知道我哪里出错了,或者这是它应该如何工作

2 个答案:

答案 0 :(得分:2)

这种情况是OGM关系不明确的原因,因为它们存在于相同类型但存在于特定方向之间。

(john)-[:KNOWS]->(george)也暗示乔治应该有来自约翰的传入关系,但域模型并没有反映这一点。在后续保存中,正如您所注意到的那样,关系会被删除,因为映射器由于模糊性而无法确定要保留的内容。

当您在相同类型的实体之间存在这种关系时,明确关系方向就是解决方案。 在你的情况下,从一个人到另一个人的关系总是处于传出方向,所以添加这样的方向可以清楚地表明OGM不会担心相同类型的传入关系。

@Relationship(type = "KNOWS", direction = "OUTGOING")
Set<Person> myTypes;

另外,你不必拯救每个人 - 在你的例子中,拯救约翰就足够了,因为OGM可以从约翰转移到乔治和安,从而到达挖掘。

答案 1 :(得分:0)

我认为问题在于您保存Person对象的方式。 一种解决方案是首先保存人物对象。然后添加关系并重新保存您添加关系的实体,而不是添加的实体。

例如

    Person john = new Person("John","P");
    Person Ann = new Person("Ann","M");

    Set<Person> Persons= new HashSet<Person>();
    Persons.add(Ann);
    john.setMyTypes(Persons);
    personRepository.save(john);

以上将拯救约翰和安,并将建立一个关系&#34; KNOWS&#34;它们之间。不需要再次拯救安。

如果您尝试在上述代码

之后再次保存Ann
personRepository.save(Ann); 

关系将被删除,因为neo4j会将其视为一个没有任何关系的实体,因为当Ann对象之前创建时关系不存在