Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
06-02-2022 06:55 AM
Hi ,
I am trying to add a dummy node between two nodes and copy the relationship type on its outgoing and incoming edges. My nodes have a lvl property and if a lvl 1 is directly connected to a lvl 3 I add a dummy node with lvl 2 in between. The relationship type isnt defined and may change between different node pairs.
EG : A{lvl:1} -[*]-> C[lvl:3}
I need to add B with lvl :2 : A{lvl:1} -[*]->B{lvl:2}-[*]-> C[lvl:3}
Solved! Go to Solution.
06-02-2022 07:29 AM - edited 06-02-2022 07:39 AM
Hello @gdb_ONE 🙂
This query works on the version 4.4 at least of Neo4j with the APOC plugin but it should do what you asked:
MATCH (a:Node {lvl: 1})-[r]->(b:Node {lvl: 3})
CALL {
WITH a, r, b
CALL apoc.cypher.doIt('
WITH a, b
CREATE (n:Node {lvl: 2})
MERGE (a)-[:`'+type(r)+'`]->(n)
MERGE (n)-[:`'+type(r)+'`]->(b)
RETURN *
', {a:a, b:b})
YIELD value
DELETE r
} IN TRANSACTIONS
I have to use apoc.cypher.doIt() procedure since we want to execute a writing transaction and that it's the only wait to setup the type dynamically in Cypher.
If you execute this query in Neo4j Browser, you have to add :auto front of the query. The subquery is used to optimized the process if you have to scan the whole database
Regards,
Cobra
06-15-2022 12:07 AM
Hello @gdb_ONE
MATCH (a:Node {lvl: 1})-[r]->(b:Node {lvl: 3})
WITH a, b, collect(r) AS relations
CALL {
WITH a, b, relations
CREATE (n:Node {lvl: 2, name: "F"})
WITH a, b, n, relations
UNWIND relations AS r
CALL apoc.merge.relationship(a, type(r), {}, {}, n, {}) YIELD rel WITH b, n, r
CALL apoc.merge.relationship(n, type(r), {}, {}, b, {}) YIELD rel WITH r
DELETE r
} IN TRANSACTIONS
Don't forget to add :auto front of the query if you execute it from the browser.
Regards,
Cobra
06-02-2022 07:29 AM - edited 06-02-2022 07:39 AM
Hello @gdb_ONE 🙂
This query works on the version 4.4 at least of Neo4j with the APOC plugin but it should do what you asked:
MATCH (a:Node {lvl: 1})-[r]->(b:Node {lvl: 3})
CALL {
WITH a, r, b
CALL apoc.cypher.doIt('
WITH a, b
CREATE (n:Node {lvl: 2})
MERGE (a)-[:`'+type(r)+'`]->(n)
MERGE (n)-[:`'+type(r)+'`]->(b)
RETURN *
', {a:a, b:b})
YIELD value
DELETE r
} IN TRANSACTIONS
I have to use apoc.cypher.doIt() procedure since we want to execute a writing transaction and that it's the only wait to setup the type dynamically in Cypher.
If you execute this query in Neo4j Browser, you have to add :auto front of the query. The subquery is used to optimized the process if you have to scan the whole database
Regards,
Cobra
06-02-2022 11:17 PM
Thank you for your reply :).
I had two follow-up doubts/questions:
I wanted to know what 'IN TRANSACTION' does as I am not well versed in apoc statements.
I tried to add a name to the new node that was being created in the statement Create (n:Node {name:'F', lvl:'2'}) but got this error :"
Invalid input 'F': expected whitespace, '.', node labels or rel types, '[', '^', '*', '/', '%', '+', '-', "=~", IN, STARTS, ENDS, CONTAINS, IS, '=', "<>", "!=", '<', '>',/ "<=", ">=", AND, XOR, OR, ',' or ')' (line 4, column 32 (offset: 152))
is this because of apoc statement? cause i could normally add properties like this to nodes
06-02-2022 11:31 PM
It's just a problem of quotation marks, you have to use "F" and not 'F':
MATCH (a:Node {lvl: 1})-[r]->(b:Node {lvl: 3})
CALL {
WITH a, r, b
CALL apoc.cypher.doIt('
WITH a, b
CREATE (n:Node {lvl: 2, name: "F"})
MERGE (a)-[:`'+type(r)+'`]->(n)
MERGE (n)-[:`'+type(r)+'`]->(b)
RETURN *
', {a:a, b:b})
YIELD value
DELETE r
} IN TRANSACTIONS
Regards,
Cobra
06-10-2022 12:35 AM - edited 06-10-2022 05:48 AM
Hello @Cobra ,
I was trying to update the query for a case where there are two or more relationships between the nodes A and C and I wanted a node B with the same amount of relationships coming in and going out without creating multiple B
eg A=C -> A=B=C
06-14-2022 05:55 AM
Hello @Cobra ,
I updated your query to insert node between nodes with 2 relationship between them but it gives an error in some cases while runs for some
MATCH (a:A {lvl:"1"})-[r]->(b:A {lvl:"3"})
WITH a, collect(r) as r, b
CALL apoc.cypher.doIt('
WITH a, b
CREATE (n:A {name:"F",lvl: "2"})
MERGE (a)-[:`'+type(r[0])+'`]->(n)
MERGE (n)-[:`'+type(r[0])+'`]->(b)
MERGE (a)-[:`'+type(r[1])+'`]->(n)
MERGE (n)-[:`'+type(r[1])+'`]->(b)
RETURN *
', {a:a, b:b})
YIELD value
DELETE r[0],r[1] (had to remove call in transactions as i couldnt write collect in with clause )
it gives this error
Failed to invoke procedure `apoc.cypher.doIt`: Caused by: org.neo4j.exceptions.SyntaxException: Invalid input 'null': expected "," "CALL" "CREATE" "DELETE" "DETACH" "FOREACH" "LIMIT" "LOAD" "MATCH" "MERGE" "OPTIONAL" "ORDER" "REMOVE" "RETURN" "SET" "SKIP" "UNION" "UNWIND" "USE" "WHERE" "WITH" <EOF> (line 1, column 35 (offset: 34)) " WITH $`a` as `a` , $`b` as `b` null"
06-15-2022 12:07 AM
Hello @gdb_ONE
MATCH (a:Node {lvl: 1})-[r]->(b:Node {lvl: 3})
WITH a, b, collect(r) AS relations
CALL {
WITH a, b, relations
CREATE (n:Node {lvl: 2, name: "F"})
WITH a, b, n, relations
UNWIND relations AS r
CALL apoc.merge.relationship(a, type(r), {}, {}, n, {}) YIELD rel WITH b, n, r
CALL apoc.merge.relationship(n, type(r), {}, {}, b, {}) YIELD rel WITH r
DELETE r
} IN TRANSACTIONS
Don't forget to add :auto front of the query if you execute it from the browser.
Regards,
Cobra
06-15-2022 11:55 PM - edited 06-16-2022 12:13 AM
Thanks a lot @Cobra I am really starting to understand how to search for apoc procedures as per my requirement. Just one question the code works for both single and double relationships present between two nodes.. was there a reason you used cypher.do.it the first time for single relationships ?
I feel you did it because there wasnt a need to introduce collect, unwind if I specified only one relationship but do correct me if I am wrong
06-16-2022 12:38 AM
No problem 🙂 When I first replied to your topic I used the apoc.cypher.doIt() procedure but for the new answer I remembered there was an apoc.merge.relationship() procedure to dynamically create relationships. I think apoc.merge.relationship() is less dirty than apoc.cypher.doIt() for your case 🙂
All the sessions of the conference are now available online