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



我正在使用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;

 }

我正在尝试创建一个类似"

约翰-知道->乔治和约翰-知道->安。 安-知道->挖

'。以下是我设置域对象和持久化的方式。

    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(john)创建了具有关系的节点,但在随后的保存期间,所有关系都被删除了。下面是日志中打印的内容,并清楚地表明关系已删除。

 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}]}

不知道我哪里出了问题,或者这就是它应该工作的方式

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

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

当您在相同类型的实体之间具有这些关系时,明确关系方向是解决方案。在您的情况下,从一个人到另一个人的关系总是在传出方向上,因此添加这样的方向可以清楚地表明 OGM 不必担心相同类型的传入关系。

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

此外,您不必拯救每个人 - 在您的示例中,保存约翰就足够了,因为 OGM 可以从约翰遍历到乔治和安,从而到达 Dug。

我认为问题出在您保存 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);

以上将拯救约翰和安,并将在他们之间建立"知道"的关系。没必要再救安了。

如果您尝试再次保存 Ann,请在上述代码之后

personRepository.save(Ann); 

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

相关内容

  • 没有找到相关文章

最新更新