cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

How to Update Relationship In SDN 6 ?

Currently, We're working on OGM base implementation. We like to move on SDN 6 But I face problem to update relationship by neo4jRepository. I mention domain model.

@Node
public class Activity {
    @Id
    @GeneratedValue
    protected Long graphId;
    private String guid;
    @Relationship(type = "PARENT_OF", direction = Direction.OUTGOING)
    private Set<Activity> children;
    
     public void addChild(Activity child) {
      this.children.add(child);
    }
    public void removeChild(Activity child) {
     this.children.remove(child);
    }

}
public interface ActivityReadRepository extends Neo4jRepository<Activity, Long>{
}
@Component
public class RunableClass implements CommandLineRunner{
 @Autowired
    ActivityRepository activityRepository;
@Override
    public void run(String... args) throws Exception {
Activity parent = activityRepository.findByGuid("xxx-xxx-xxx-xxx-xxx")

Activity child = activityRepository.findByGuid("xxx-xxx-xxx-xxx-xxx1")

parent.removeChild(child);
activityRepository.save(parent);
}
 }

After used save() Method, All Child `PARENT_OF`  relationship will be removed. That above code working fine in SDN+OGM, but it does not work on SDN 6. 

8 REPLIES 8

Has your ` findByGuid`  method a custom query annotation? I ask because it seems that the parent is not fully hydrated. 
SDN will remove and re-create all relationships to keep the Java model(s) in sync with the database. (https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#query-creation.save)

If you don't want / can load the full ` Activity`` , it might also be helpful to have a look at the projection support in SDN that will only load and/or persist a part of your domain. https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#projections 

 ` findByGuid`   do not custom query. I try to fetch full  `Activity`.

 

public interface ActivityReadRepository extends Neo4jRepository<Activity, Long>{
    Activity findByGuid(String Guid)
}

 

I used about code for fetch parent and child Activity.
I want to change parent of Child Activity. But it does not work. Do Projection update relationship ? I asked because i used projection, it did the same as by entity.


Yes, it would also work the same way with projection. But I it was more related in cases you do not want to fetch everything (maybe a topic later).

Have you checked the activity parent entity before the save? Does it contain other ` Parent_Of`  elements at all?
Although it should not make any differences, you could try to remove the child from the parent's list by iterating through the already loaded children list and removing the child with the given uuid.

1) Have you checked the activity parent entity before the save ?
Yes  checked its contain child activity
 
ravi_arsuda_0-1658490801618.png
I used projection to save children.

 

public class ActivityDetails {

    private Long graphId;
    private Set<Activity> children;
    public Long getGraphId() {
    
        return graphId;
    }
    
    public void setGraphId(Long graphId) {
    
        this.graphId = graphId;
    }
    
    public Set<Activity> getChildren() {
    
        return children;
    }
    
    public void setChildren(Set<Activity> children) {
    
        this.children = children;
    } 
    
}
@Component
public class RunableClass implements CommandLineRunner{
@Autowired
    Neo4jTemplate neo4jTemplate;
@Override
    public void run(String... args) throws Exception {
        ActivityDetails activityInf =activityReadRepository.findByGraphId(167L); // Without @Query annotation
        neo4jTemplate.save(Activity.class).one(activityInf);
   }
 }

 

After saved, I  got below logs.

 

2022-07-22 11:42:12,305Z | DEBUG | main | org.springframework.data.neo4j.cypher                   | correlationId:- | Executing:
OPTIONAL MATCH (hlp:`Activity`:`AbstractGraphNodeEntity`:`IGraphNodeEntity`) WHERE id(hlp) = $__id__ WITH hlp WHERE hlp IS NULL CREATE (activity:`Activity`:`AbstractGraphNodeEntity`:`IGraphNodeEntity`) SET activity = $__properties__ RETURN activity UNION MATCH (activity:`Activity`:`AbstractGraphNodeEntity`:`IGraphNodeEntity`) WHERE id(activity) = $__id__ SET activity += $__properties__ RETURN activity 
2022-07-22 11:42:12,323Z | DEBUG | main | org.springframework.data.neo4j.cypher                   | correlationId:- | Executing:
MATCH (startNode)-[rel:`PARENT_OF`]->(:`Activity`:`AbstractGraphNodeEntity`:`IGraphNodeEntity`) WHERE (id(startNode) = $fromId AND NOT (id(rel) IN $__knownRelationShipIds__)) DELETE rel 

 

I don't know why it deleted Parent_of relationship in save method. If it already contains in projection class.

I need to ask this explicitly before investigating further: As described in the linked documentation, the removal of all PARENT_OF relationships is nothing unusual.
Is this your problem or that there are no relationships is the database anymore.

Sorry to ask but I am not 100% sure what the question is.

Database contain PARENT_OF relationship, If I try to update current relationship by save method, SDN removed all sub graph node relationship as i mansion before.
I only need to update a targeted node of  relationship. When tried it by projection as well as with repository, it did not work. It removed current relationship. Yes, it is a problem.


 

gerrit_meier
Neo4j
Neo4j

I could not exactly reproduce your problem but I think it is the very same root cause:
When fetching the parent and the child separately, parent's child and loaded child are different objects.
Removing the child would fail if it does not "look like" the one that is in the parent's collection.

To remove the child properly from the list, you have to implement equals/hashCode like

 

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Activity activity = (Activity) o;
        return graphId.equals(activity.graphId) && guid.equals(activity.guid);
    }

    @Override
    public int hashCode() {
        return Objects.hash(graphId, guid);
    }

 

I created an example based on the information you provided: https://github.com/meistermeier/neo4j-issues-examples/tree/master/community-58196

Okay