I want to delete node with all incoming and outgoing relationships.
This incoming and outgoing relationships are optional.
(t:Teacher)-[:TEACHES]->(s:Student)
(s:Student)-[:ATTENDS]->(c:Class)
Student node have optional relationship with Teacher and optional relationship with Class.
I want to delete Student node with {id:1}.
I know how to delete all nodes and relationships with:
MATCH (n)
OPTIONAL MATCH (n)-[r]-()
DELETE n,r
But not able to convert it for specific node. Please help.
Just add the discriminating property to the first match clause
MATCH (s:Student {id:1})
OPTIONAL MATCH s-[r]-()
DELETE r, s
If instead by id you mean the internal node id and not a property that you have set, then
MATCH (s)
WHERE ID (s) = 1
OPTIONAL MATCH s-[r]-()
DELETE r, s
should work. It is irregular and usually bad to lay hold of nodes by their internal id.
You're very close:
match (n:Student)
where n.studentid = 2224
optional match (n)-[r]-()
delete n,r
(updated based on jjaderberg's comment)
Related
I have a following part of Cypher query:
MATCH (ch:Characteristic) WHERE id(ch) = {characteristicId} WITH ch OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)...
first of all I'm looking for (ch:Characteristic) by characteristicId and then applying required logic for this variable at the rest of my query.
my Characteristic can also have(or not) a child Characteristic nodes, like:
(ch:Characteristic)-[:CONTAINS]->(childCh)
Please help to extend my query in order to collect ch and childCh into a list of Characteristic thus I'll be able at the rest of my query to apply required logic to all Characteristic at this list.
UPDATED - possible solution #2
This is my current working query:
MATCH (chparent:Characteristic)
WHERE id(chparent) = {characteristicId}
OPTIONAL MATCH (chparent)-[:CONTAINS*]->(chchild:Characteristic)
WITH chparent, collect(distinct(chchild)) as childs
WITH childs + chparent as nodes
UNWIND nodes as ch
OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)-[:SET_FOR]->(Decision)
OPTIONAL MATCH (v)-[:CONTAINS]->(vE) OPTIONAL MATCH (vE)-[:CONTAINS]->(vEE)
OPTIONAL MATCH (ch)-[:CONTAINS]->(cho:CharacteristicOption)
OPTIONAL MATCH (cho)-[:CONTAINS]->(choE) OPTIONAL MATCH (ch)-[:CONTAINS]->(chE)
DETACH DELETE choE, cho, ch, vEE, vE, v, chE
This is an attempt to simplify the query above:
MATCH (ch:Characteristic)
WHERE (:Characteristic {id: {characteristicId}})-[:CONTAINS*]->(ch)
OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)-[:SET_FOR]->(Decision)
OPTIONAL MATCH (v)-[:CONTAINS]->(vE)
OPTIONAL MATCH (vE)-[:CONTAINS]->(vEE)
OPTIONAL MATCH (ch)-[:CONTAINS]->(cho:CharacteristicOption)
OPTIONAL MATCH (cho)-[:CONTAINS]->(choE)
OPTIONAL MATCH (ch)-[:CONTAINS]->(chE)
DETACH DELETE choE, cho, ch, vEE, vE, v, chE
but this query doesn't delete required Characteristic nodes and my tests fail. What am I doing wrong at the last query ?
You can try something like this with apoc:
MATCH (chparent:Characteristic {characteristicId: <someid>})
OPTIONAL MATCH (chparent)-[:CONTAINS]->(chchild:Characteristic)
WITH apoc.coll.union(chparent,chchild) as distinctList
...
With pure cypher you can try something like this:
MATCH (chparent:Characteristic {characteristicId: <someid>})
OPTIONAL MATCH (chparent)-[:CONTAINS]->(chchild:Characteristic)
WITH chparent,collect(distinct(chchild)) as childs
WITH chparent + childs as list
....
Not really sure if you need distinct in collect, but I added just so you know you can do this to filter out duplicates.
You can actually do this easily by using a variable-length relationship match of 0..1, as it will let you match on your root :Characteristic node and any of its children.
MATCH (chparent:Characteristic)-[:CONTAINS*0..1]->(ch:Characteristic)
WHERE id(chparent) = {characteristicId}
// ch contains both the parent and children, no need for a list
...
A more simplified query.
MATCH (c:Characteristics) WHERE (:Characteristics {id: 123})-[:CONTAINS*0..1]->(c) return c;
Matches all Characteristics including the root node that (optionally) have incoming relationships of type CONTAINS from the node specified with id 123.
I assume all the children of Characteristic will also have the label Characteristic. Another assumption I made is, you need characteristicId which is defined by you, not the internal id defined by neo4J. id(ch) fetching the internal id instead of user defined ID. You might want to pass the characteristicId variable like I gave here.
MATCH (chparent:Characteristic {characteristicId: <someid>})
WITH chparent
OPTIONAL MATCH (chparent)-[:CONTAINS]->(chchild:Characteristic)
WITH chchild
<your operation>
NOT RELEVANT - SKIP TO Important Edit.
I have the following query:
MATCH (n)
WHERE (n:person) AND n.id in ['af97ab48544b'] // id is our system identifier
OPTIONAL MATCH (n)-[r:friend|connected|owner]-(m)
WHERE (m:person OR m:dog OR m:cat)
RETURN n,r,m
This query returns all the persons, dogs and cats that have a relationship with a specific person. I would like to turn it over to receive all the nodes & relationships that NOT includes in this query results.
If it was SQL it would be
select * from graph where id NOT IN (my_query)
I think that the OPTIONAL MATCH is the problematic part. I How can I do it?
Any advice?
Thanks.
-- Important Edit --
Hey guys, sorry for changing my question but my requirements has been changed. I need to get the entire graph (all nodes and relationships) connected and disconnected except specific nodes by ids. The following query is working but only for single id, in case of more ids it isn't working.
MATCH (n) WHERE (n:person)
OPTIONAL MATCH (n)-[r:friend|connected|owner]-(m) WHERE (m:person OR m:dog OR m:cat)
WITH n,r,m
MATCH (excludeNode) WHERE excludeNode.id IN ['af97ab48544b']
WITH n,r,m,excludeNode WHERE NOT n.id = excludeNode.id AND (NOT m.id = excludeNode.id OR m is null)
RETURN n,m,r
Alternatively I tried simpler query:
MATCH (n) WHERE (n:person) AND NOT n.id IN ['af97ab48544b'] return n
But this one does not returns the relationships (remember I need disconnected nodes also).
How can I get the entire graph exclude specific nodes? That includes nodes and relationships, connected nodes and disconnected as well.
try this:
match (n) where not n.id = 'id to remove' optional match (n)-[r]-(m)
where not n.id in ['id to remove'] and not m.id in ['id to remove']
return n,r,m
You've gotta switch the 'perspective' of your query... start by looping over every node, then prune the ones that connect to your person.
MATCH (bad:person) WHERE bad.id IN ['af97ab48544b']
WITH COLLECT(bad) AS bads
MATCH path = (n:person) - [r:friend|:connected|:owner] -> (m)
WHERE n._id = '' AND (m:person OR m:cat OR m:dog) AND NOT ANY(bad IN bads WHERE bad IN NODES(path))
RETURN path
That said, this is a problem much more suited to SQL than to a graph. Any time you have to loop over every node with a label, you're in relational territory, the graph will be less efficient.
I have got a set of nodes and I would like to write a query to find every relationships which exist between these nodes.
Any recommendation?
My first attemp would be a MATCH a-[rel]-b WHERE... and my WHERE clause would be a OR of all the ids I have in my set of nodes.
Any better idea?
In these answers, I assume you will pass the ID list as a parameter named ids.
If you want to exclude relationships from a node to itself:
MATCH (a)-[r]-(b)
WHERE id(a) IN {ids} AND id(b) IN {ids} AND a <> b
RETURN r;
If you want to include relationships from a node to itself:
MATCH (a)-[r]-(b)
WHERE id(a) IN {ids} AND id(b) IN {ids}
RETURN r;
You could do something like this:
MATCH (a)-[rel]-()
WHERE ID(a) IN {node_ids}
RETURN rel, ID(rel), type(rel), ID(startNode(rel)), ID(endNode(rel))
Here you'd be passing in a node_ids parameter which would be an array.
Note also that using internal Neo4j IDs for long-term reference to nodes may break if Neo4j defragments the nodes.
In SQL:
Delete From Person Where ID = 1;
In Cypher, what's the script to delete a node by ID?
(Edited: ID = Neo4j's internal Node ID)
Assuming you're referring to Neo4j's internal node id:
MATCH (p:Person) where ID(p)=1
OPTIONAL MATCH (p)-[r]-() //drops p's relations
DELETE r,p
If you're referring to your own property 'id' on the node:
MATCH (p:Person {id:1})
OPTIONAL MATCH (p)-[r]-() //drops p's relations
DELETE r,p
The cleanest sweep for a node with id "x" is
MATCH (n) where id(n) = x
DETACH DELETE n
https://neo4j.com/docs/cypher-manual/current/clauses/delete/#delete-delete-a-node-with-all-its-relationships
https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-id
Old question and answered, but to delete node when it has relationships, use DETACH
MATCH (n) where ID(n)=<your_id>
DETACH DELETE n
or otherwise you get this:
Neo.ClientError.Schema.ConstraintValidationFailed: Cannot delete node<21>, because it still has relationships. To delete this node, you must first delete its relationships.
It's like SQL's CASCADE
When the node is a orphan.
Start n=node(1)
Delete n;
Following the link provided by #saad-khan, here's an example for getting the nodes and relationships ids.
The code below shows the ids, so you can make sure that you're deleting everything related to the given ID.
MATCH (node)-[relation:HAS]->(value)
where ID(node)=1234
RETURN ID(instance), ID(value), ID(r)
Ps.: ":HAS" is an example of an relationship.
How to delete multiple nodes, (NOT ALL) in neo4j?
I have this queryMATCH (n)
where n.name IS NULL
delete n
It returns more than one node, I want to delete all those nodes(All nodes, which are mistakenly created thats why become null).
The error, I am facing is
javax.transaction.HeuristicRollbackException: Failed to commit transaction Transaction(11, owner:"qtp16626756-84")[STATUS_NO_TRANSACTION,Resources=1], transaction rolled back ---> javax.transaction.xa.XAException
CASE 2: What to do in case of NOT NULL (property) but no any relationship is associated within a node or two; means a node which is kind of orhpan, not connected with other node.
I tried to use LIMIT/SKIP but not working.Any help?
You need to also delete any relationships connected to those nodes, like so:
match (n)
where n.name IS NULL
optional match (n)-[r]-()
delete n, r
Update for your second case (this deletes only orphans):
match (n)
where NOT (n)--()
and n.name IS NULL
delete n