0
votes

I have the following entities:

@NodeEntity(label = "A")
public class A {
    @Property(name = "something")
    private String someProperty;

    //... getters and setters
}

@NodeEntity(label = "B")
public class B {
    @Property(name = "someOtherThing")
    private String otherProperty;

    //... getters and setters
}

@RelationshipEntity(type = "AB")
public class AB {
    @StartNode
    private A start;

    @EndNode
    private B end;

    @Property(name = "evenOtherThing")
    private String prop;

    //... getters and setters
}

So, in this situation I have (:A)-[:AB]->(:B). I can have several ABs (meaning I can connect A to B several times, having different properties each time).

With that configuration I can save AB instances without problems, but when it comes to deleting just the relationship, I couldn't find a way to do so, using the spring-data-neo4j methods.

Things that I tried:

1- Custom query:

@Repository
public interface ABRepository extends GraphRepository<AB> {

    @Query("MATCH (a:A)-[ab:AB]->(b:B) WHERE a.something={something} DELETE ab")
    void deleteBySomething(@Param("something") String something);
}

Usage:

@Autowired
ABRepository repository;

//...
repository.deleteBySomething(something);

It didn't work as expected. The A node is removed altogether with the AB relationship. If I run the query directly at the database, it works as expected.

2- Delete from the repository:

@Repository
public interface ABRepository extends GraphRepository<AB> {

    @Query("MATCH (a:A)-[ab:AB]->(b:B) WHERE a.something={something} RETURN a,ab,b")
    Iterable<AB> findBySomething(@Param("something") String something);
}

Usage:

Iterable<AB> it = repository.findBySomething(something);
repository.delete(it);

Same stuff. The nodes are removed. I tried to iterate over the Iterable<AB> and remove the relationships one by one, without success as well.

3- Nulling the references of A and B inside AB and saving AB:

Same code of the repository, with a different usage:

Iterable<AB> it = repository.findBySomething(something);
for (AB ab : it) {
    ab.setA(null);
    ab.setB(null);
}
repository.save(it);

Here I'm just trying random stuff. It didn't work as expected. The framework rises an exception stating that the start and end nodes can't be null.

So, what am I doing wrong? What does it take to remove a simple relationship from the database using spring-data-neo4j, without removing the linking nodes?

For the record: my neo4j database is v.3.0.4 and my spring-data-neo4j is v.4.1.4.RELEASE. Running Java 8.

1
Cannot reproduce with this gist. Can you check the differences ?nmervaillie

1 Answers

2
votes

In the end the problem was a sum of two factors.

First: not mentioned in the question, but the way I saved the AB entity wasn't ideal. I was using repository.save(ab) directly, and that can make the framework do some magic with the A and B entities inside. To save just the relationship, without touching the related entities, the repository.save(ab, 0) should be used.

Second: removing entities using a custom query is intuitively faster than fetching the entities and then removing them, so using that approach was my first goal. And here again I was confused by some magic behind the scenes, better described at this question: Spring Data Neo4j 4returning cached results?

In summary, after removing entities or relationships using custom queries, I should clear the session:

@Autowired
Session session;

//...
repository.deleteBySomething(something);
session.clear();

These two tweaks fixed the weird behavior I was having with the framework.