Neo4J - FOREACH CASE WHEN PATH EXISTS, DELETE RELATIONSHIP - foreach

I'm attempting to match a parent-child relationship. I have a case where a child node may link to a different 'grandparent'. In this case, I want to delete the relationship between the child and the grandparent so that I mitigate the potential issue that the grandparent is recognised also as a child node and is then deleted.
MATCH (c: itemContainer {uuid: "$ID"})<-[:HAS_VERSION]-(cv: itemContainerVersion {version: 1})
WITH c, cv
MATCH (parent)-[*0..]-(child)
WHERE (parent)--(cv)-[:HAS_VERSION]->(c)
WITH DISTINCT parent, child, cv, c
MATCH (child)-[cvr]-(n)--(cv2: itemContainerVersion)
WITH child, cv, c, cvr
FOREACH(i IN CASE WHERE exists(cvr) THEN [1] ELSE [] END | DELETE cvr)
FOREACH(i IN CASE WHERE NOT exists(cvr) THEN [1] ELSE [] END | DETACH DELETE child)
DETACH DELETE parent, cv, c
RETURN parent, child, cv, c
I get an issue in the first FOREACH statement:
Neo.ClientError.Statement.SyntaxError: Invalid input 'x': expected 'n/N' (line 10, column 27 (offset: 351))
" FOREACH(i IN CASE WHERE exists(cvr) THEN [1] ELSE [] END | DELETE cvr)"
^
I don't understand why this is broken. It seems to be an issue with the exists() - maybe a type error?

WHEN instead of WHERE.
MATCH (c: itemContainer {uuid: "$ID"})<-[:HAS_VERSION]-(cv: itemContainerVersion {version: 1})
WITH c, cv
MATCH (parent)-[*0..]-(child)
WHERE (parent)--(cv)-[:HAS_VERSION]->(c)
WITH DISTINCT parent, child, cv, c
MATCH (child)-[cvr]-(n)--(cv2: itemContainerVersion)
WITH child, cv, c, cvr
FOREACH(i IN CASE WHEN exists(cvr) THEN [1] ELSE [] END | DELETE cvr)
FOREACH(i IN CASE WHEN NOT exists(cvr) THEN [1] ELSE [] END | DETACH DELETE child)
DETACH DELETE parent, cv, c
RETURN parent, child, cv, c

Related

How do I choose to create a node based on whether it exists in the database in neo4j?

I tried the following but it threw this error. I wish to only create a new person node if there isnt a person node in the existing database that has the exact same properties.
org.neo4j.driver.exceptions.ClientException: Invalid input 'R': expected
MERGE (n:Person{id: abc.id})
MERGE (m:Place{place:def.id})
MERGE (o:Thing{id:abcd.id})
WITH n,m,o
OPTIONAL MATCH (n) – [:present_at] -> x with n,m,o, collect (distinct x) as known_place
OPTIONAL MATCH (m) – [:is] -> y with n,m,o, collect (distinct y) as known_thing
FOREACH (a in ( CASE WHEN NOT m IN known_place THEN [1] ELSE [] END ) CREATE (n)-[:present_at] ->(m))
FOREACH (a in ( CASE WHEN NOT o IN known_thing THEN [1] ELSE [] END ) CREATE (m)-[:is] ->(o))
That error was caused by a missing | in each of your FOREACH clauses. For example, this would fix that syntax error:
FOREACH (a in ( CASE WHEN NOT m IN known_place THEN [1] ELSE [] END ) | CREATE (n)-[:present_at] ->(m))
FOREACH (a in ( CASE WHEN NOT o IN known_thing THEN [1] ELSE [] END ) | CREATE (m)-[:is] ->(o))
However, your query would still have numerous other syntax errors.
In fact, the entire query could be refactored to be simpler and more efficient:
WITH {id: 123} AS abc, {id: 234} as def, {id: 345} AS abcd
MERGE (n:Person{id: abc.id})
MERGE (m:Place{place: def.id})
MERGE (o:Thing{id: abcd.id})
FOREACH (a in ( CASE WHEN NOT EXISTS((n)–[:present_at]->(m)) THEN [1] END ) | CREATE (n)-[:present_at]->(m))
FOREACH (a in ( CASE WHEN NOT EXISTS((m)–[:is]->(o)) THEN [1] END ) | CREATE (m)-[:is]->(o))

Cypher: If node not exists, create multiple nodes and relations

I want to MERGE a node:
MERGE (a: Article {URL: event.URL})
If the node does not exist, I need to do this:
ON CREATE FOREACH( site_name in CASE WHEN event.site_name is not null then [1] ELSE [] END |
MERGE (w: Website { value: event.site_name})
MERGE (w)-[:PUBLISHED]->(a))
// all of the tag creation
FOREACH( tag in CASE WHEN event.tags is not NULL then event.tags else [] END |
Merge (t: Article_Tag {value: tag})
CREATE (a)-[: HAS_ARICLE_TAG {date:event_datetime}]->(t))
I believe that ON CREATE only works with SET, but as above, i need to execute multiple statements. Is there a way to create multiple nodes and relationships with an ON CREATE clause?
EDIT: I have tried ON CREATE FOREACH(ignoreme in case when event.article is not null then [1] else [] end |... multiple statements but this does not escape the SET problem.
This is the best way to do this: just wrap it in a FOREACH statement
MATCH (a: Article {URL: event.URL})
FOREACH(ignoreme in case when a is not null then [1] else [] end |... Statement here...)

(Neo4j, Cypher) How to set incremental number to relationships?

i'm using neo4j. what i'd like to do is to create a root node for search result and to create relationships from root node to search result nodes. and I'd like to set incremental number to each relationship's property.
if possible, with one query.
Sorry for not explaining enough.
This is what I'd like to do.
Any more concise way?
// create test data
WITH RANGE(0, 99) AS indexes,
['Paul', 'Bley', 'Bill', 'Evans', 'Robert', 'Glasper', 'Chihiro', 'Yamanaka', 'Fred', 'Hersch'] AS names
UNWIND indexes AS index
CREATE (p:Person { index: index, name: (names[index%10] + toString(index)) });
// create 'Results' node with relationships to search result 'Person' nodes.
// 'SEARCH_RESULT' relationships have 'order' and 'orderBy' properties.
CREATE(x:Results{ts: TIMESTAMP()})
WITH x
MATCH(p:Person)
WHERE p.name contains '1'
MERGE(x)-[r:SEARCH_RESULT]->(p)
WITH x, r, p
MATCH (x)-[r]->(p)
WITH x, r, p
ORDER BY p.name desc
WITH RANGE(0, COUNT(r)-1) AS indexes, COLLECT(r) AS rels
UNWIND indexes AS i
SET (rels[i]).order = i
SET (rels[i]).orderBy = 'name'
RETURN rels;
// validate
MATCH(x:Results)-[r:SEARCH_RESULT]->(p:Person)
RETURN r, p.name ORDER BY r.order;

Neo4j - Cypher node and relationship relation

I have the following query:
MATCH (dg:DecisionGroup)-[:CONTAINS]->(childD:Decision)
WHERE dg.id = {decisionGroupId}
MATCH (filterCharacteristic1:Characteristic)
WHERE filterCharacteristic1.id = 1
WITH dg, filterCharacteristic1
CALL apoc.index.between(childD,'HAS_VALUE_ON',filterCharacteristic1,'(value:(10))') YIELD rel
WITH DISTINCT rel, childD, dg
MATCH (childD)-(rel) // here I need to go further only with 'childD' nodes that have relationship with 'rel'(match `apoc.index.between` predicate)
As you may see from the query above - at the end I'm trying to filter childD nodes that have the relationship with rel but I don't know how to describe it in Cypher. Something like (childD)-(rel) or (childD)-[rel] doesn't work and leads to the error. Please help
You need to look for a match pattern and compare the relationship:
...
WITH DISTINCT rel, childD, dg
MATCH (childD)-[tmp]-() WHERE tmp = rel
RETURN rel, child, dg
Or you can compare directly:
...
WITH DISTINCT rel, childD, dg, startNode(rel) AS sRel, endNode(rel) AS eRel
WHERE (childD)--(sRel) OR (childD)--(eRel)
RETURN rel, child, dg

Neo4j - Dynamic delete cypher query

I have following data structure of neo4j database:
USER
/ |
/ |
LIST |
\ |
\ |
CONTACT
means, USER have a relationship with LIST and LIST have relationship with CONTACT, but in some case, USER might have relationship with CONTACT (not all time). Now I want to delete CONTACT's data. I have write the following query:
MATCH (b:USER { id: {id} } )-[relationship01]->(pl:LIST {id: {listId} )
OPTIONAL MATCH (pl)-[cnpt:USER_LIST]->(cn:CONTACTS {id: {contactId} } )
DELETE cnpt, cn;
This query delete CONTACT with relationship with LIST. But in some case, I also have to delete relationship with USER. To solve this, I have write the following query:
MATCH (b:USER { id: {id} } )-[relationship01]->(pl:LIST {id: {listId} )
OPTIONAL MATCH (pl)-[cnpt:USER_LIST]->(cn:CONTACTS {id: {contactId} } )
OPTIONAL MATCH (b)-[bur]->(cnx:CONTACTS {id: {contactId} } )
DELETE cnpt, cn, bur, cnx;
This query delete CONTACT with relationship with LIST and USER, but problem is, if there is no relationship between CONTACT and USER, then it throw error.
How can I solve this problem?
Thanks in Advance.
You can't delete a node until all its relationships are deleted, which is why there is a shorthand for deleting all of a node's relationships, then the node itself: DETACH DELETE
So all you have to do is this:
MATCH (:USER { id: {id} } )-->(pl:LIST {id: {listId} )
OPTIONAL MATCH (pl)-[:USER_LIST]->(cn:CONTACTS {id: {contactId} } )
DETACH DELETE cn;

Resources