Indeed, keeping a deleted
property quickly becomes unmanageable as your graph model evolves: the property creeps into each and every one of your queries. To my knowledge, Neo4j provides nothing to help you with this.
However, I've had success with albertoperdomo's approach. Some of the details are in a question I asked here a couple of months ago.
You want to replace two things of the nodes that you want to soft delete: their labels (so they can't be looked up directly) and their relationships (so they can't be reached from other nodes). In my case, I simply prepend labels and relationship types with an underscore (_).
The benefits are clear: your existing queries are (probably!) safe because the soft-deleted nodes are no longer taken into account (they can't be reached anymore, unless you omit the relationship type obviously, i.e. (a)--(b)
or something).
I also like to think this is the most performant way of implementing a soft-delete because you're effectively cutting off pieces of your graph -- instead of matching on a property (even if it's indexed).
There is a catch, however. There is no general way to replace labels and relationships. You can't, for example say something along the lines of:
match (:Person {id: 123})-[r]-()
set type(r) = '_' + type(r);
You'll have to replace each label and relationship separately, for every type of node you have. Things also get tricky if relationships are optional, because it's hard to "carry" your initial node across the whole of your query (hence my initial question).
The way I solved this was by stringing together the different parts of the query with UNION
:
MATCH (review:Review {Id: {id}})<-[wrote:WROTE_REVIEW]-(owner)
DELETE wrote CREATE (review)<-[:_WROTE_REVIEW]-(owner)
UNION
MATCH (review:Review {Id: {id}})-[evaluates:EVALUATES]->(product)
DELETE evaluates CREATE (review)-[:_EVALUATES]->(product)
UNION
...
UNION
MATCH (review:Review {Id: {id}})
REMOVE review:Review") SET review:_Review;
Yes, you are MATCH
ing the same node in each of the subqueries, but I think the performance implications are negligible if your properties are indexed but mainly because you create/read nodes much more often than you delete them (otherwise, your DB would be empty!)