Reputation: 3076
I have a class House
and a class Room
. Each of these classes are a NodeEntity
and are persisted in separate repositories, HouseRepository
and RoomRepository
. House
contains a Set<Room>
. I want to be able to delete a Room
instance and automatically have that instance removed from the Set<Room>
inside of the House
class. Since Neo4j is a graph database, I figured that I should be able to declare a relationship between the House
and each Room
and deleting a Room
instance will take care of this automatically. The two following classes represent House
and Room
.
@NodeEntity
public class House {
@GraphId
private Long id;
@Indexed(unique=true) String uid;
@RelatedTo (type="addition", direction=Direction.OUTGOING)
@Fetch
private Set<Room> rooms;
public House(String uid, Set<Room> rooms) {
this.uid = uid;
this.rooms = rooms;
}
public House() {
this.uid = //random uid;
}
}
@NodeEntity
public class Room {
@GraphId
private Long id;
@Indexed(unique=true) String uid;
public Room(String uid) {
this.uid = uid;
}
public Room() {
this.uid = //random uid;
}
}
I am thinking that I should be able to write a Cypher query in the RoomRepository
that would take care of this, but I am not sure. I have thought of something like this:
public interface RoomRepository extends BaseRepository<Room>{
@Query("start room=node({0}) " +
"match house-[:addition*]->room" +
"delete room")
public void deleteRoomAndRemoveRoomFromHouse(String uid);
}
What is the recommended way to handle these types of deletes?
Upvotes: 0
Views: 124
Reputation: 9952
Your approach should almost work. You may bump up against an exception because you try to delete a node without first having deleted its relationship. (Unless SDN magic takes care of that for you, but I don't think it intercepts cypher queries.)
As your MATCH
clause stands, it will act as a filter, meaning that whatever is bound to the room
identifier in your start clause is only retained by the time you reach the delete
clause if it has the relevant relationship of at least depth 1. If the room you pass as a parameter does not have at least one incoming [:addition]
relationship, it is no longer bound and won't be deleted. Perhaps this is intentional, if so keep it, but add (otherwise replace it with) a match clause that binds all the rooms relationships and deletes them before you delete the room. Try something like
START room=node({0})
MATCH room-[r]-()
DELETE r, room
But I think either the repository or Neo4jTemplate
should have plenty of voodoo to take care of this kind of operation for you. Or if you use the advanced mapping with AspectJ
, you may have all kinds of chocolate chips baked into your room
entity. I know there is a NodeEntity#persist()
, I think there is a NodeEntity#remove()
as well.
Once the node is deleted, it won't show up in the Set<Room>
field of your room class. (If you use simple mapping you may have to retrieve it or sync it manually to the database, possibly a Neo4jTemplate#fetch()
, passing the Set<Room>
field, will do that for you.)
Upvotes: 1