cancel
Showing results for 
Search instead for 
Did you mean: 

Join the community at Nodes 2022, our free virtual event on November 16 - 17.

Relationships eliminated after updating node properties

pandalei97
Node Clone

Hi,

In my repository, I made a custom query to retrieve some entities.

@Query("MATCH (n {identifier:$identifier}) RETURN n;")
 List<DynamicEntityNode> findByIdentifier(@Param("identifier") String identifier);

As imagined, this query won't retrieve the relationships but only the properties of the node itself.

But when I update some node properties and save it by Repository.save(node). I see that all the relationships are eliminated in the database. I think somehow it overwrites the entity in the database but doesn't update it.

This doesn't happen if I use the native 'findById(id)' injected by SDN6.

When I retrieve a node by using 'findById', it doesn't retrieve the relationships either. But the relationships won't disappear when I save the entity by using Repository.save(node).

I don't understand where I did wrong. For me, the only difference is that instead of find the node by Id, I try to find the node by its property. The other operations are the same.

Can someone give me some potential causes of this problem ?

Thanks in advance for your help.

1 ACCEPTED SOLUTION

gerrit_meier
Neo4j
Neo4j

First of all, your observation is right: Loading just the node and persisting it, although it would have relationships, would lead to the removal of relationships on save.
This is all written in the documentation: Query creation
But there is a solution to this problem called projections. This means you create a projection of your entity without any relationships, for example. SDN will then not check those relationships on load or save operations.
Of course, and this is something for what we initially introduced the projection support, you could also use this to load the data. Given a ProjectedEntity as the projection of your entity class.

List<ProjectedEntity> findByIdentifier(String identifier);

Would create and execute the query matching only the properties and relationships defined in the ProjectedEntity interface/class.

View solution in original post

3 REPLIES 3

glilienfield
Ninja
Ninja

I constructed a prototype a while back. What I found, and why it wasn’t a match for my problem, was that SDN was managing the entire entity. If you have only the root node of a hierarchy and save it, it thinks your entity no longer has the relationships and deletes them. It keeps your persisted version in sync with your memory version.

Maybe someone more familiar can give you a work around. I didn’t like it because I have hierarchical graphs and I want to load and manipulate subgraphs of the graph. I couldn’t seem to do that.

Hi, thanks for your feedback !

Just for information, I tried to retrieve the relationships of the first level by using:

@Query("MATCH p=(n {identifier:$identifier})-[*0..1]->(m) RETURN n, collect(relationships(p)), collect(m);")
List<DynamicEntityNode> findByIdentifierWithDepthOne(@Param("identifier") String identifier);

In this case, the relationships of root node are kept but the relationships of the target node (relationships of the depth 2) are deleted.

That seems strange to me that SDN6 can't handle this. It's impossible to retrieve the entire graph when we want to update a single property.

gerrit_meier
Neo4j
Neo4j

First of all, your observation is right: Loading just the node and persisting it, although it would have relationships, would lead to the removal of relationships on save.
This is all written in the documentation: Query creation
But there is a solution to this problem called projections. This means you create a projection of your entity without any relationships, for example. SDN will then not check those relationships on load or save operations.
Of course, and this is something for what we initially introduced the projection support, you could also use this to load the data. Given a ProjectedEntity as the projection of your entity class.

List<ProjectedEntity> findByIdentifier(String identifier);

Would create and execute the query matching only the properties and relationships defined in the ProjectedEntity interface/class.