Nothing after DELETE gets executed - neo4j

I have the following query:
MATCH (u:User)
WHERE u.id = $userId
MERGE (p:Palette {name: $name})
ON CREATE
SET p.name = $name
SET p.id = apoc.create.uuid()
MERGE (u)-[cr:CREATED]->(p)
MERGE (u)-[sa:SAVED]->(p)
WITH p MATCH (p)-[in:INCLUDES]->()
DELETE in
WITH u MATCH (p:Palette)
WHERE (u)-[:SAVED]-() AND p.name = $name
FOREACH (color IN $colors |
MERGE (c:Color {hex: color.hex})
ON CREATE
SET c.hex = color.hex
MERGE (p)-[inc:INCLUDES]->(c)
Everything works as expected up to DELETE in and then nothing else happens. I get the following error:
Neo4jError: Invalid input '': expected
")"
"CALL"
"CREATE"
"DELETE"
"DETACH"
"FOREACH"
"LOAD"
"MATCH"
"MERGE"
"ON"
"OPTIONAL"
"REMOVE"
"RETURN"
"SET"
"UNWIND"
"USE"
"WITH"
How can I continue this query after the DELETE statement? If I separate this into 2 queries (the first one ending at DELETE in), then everything works as expected.

If I understand correctly, the p before the DELETE is the same as the p after it. Id this is the case, use WITH to keep the items you already searched for. So you can try:
MATCH (u:User)
WHERE u.id = $userId
MERGE (p:Palette {name: $name})
ON CREATE
SET p.name = $name
SET p.id = apoc.create.uuid()
MERGE (u)-[cr:CREATED]->(p)
MERGE (u)-[sa:SAVED]->(p)
WITH p, u MATCH (p)-[inc:INCLUDES]->()
WITH p, u, inc
DELETE inc
WITH p
FOREACH (color IN $colors |
MERGE (c:Color {hex: color.hex})
ON CREATE
SET c.hex = color.hex
MERGE (p)-[inc:INCLUDES]->(c)
I tried:
MATCH (p:Palette)
WHERE p.name = "First test palette"
MATCH (p)-[inc:INCLUDES]->(c:Color)
WITH p, inc
DELETE inc
WITH p
MATCH (u)-[:SAVED]-(p)
RETURN u, p
On this data sample:
MERGE (e:User {name: "user"})
MERGE (a:Palette {name: "First test palette"})
MERGE (b:Color {hex: "#123123"})
MERGE (c:Color {hex: "#ffffff"})
MERGE (d:Color {hex: "#000000"})
MERGE (a)-[:INCLUDES]-(b)
MERGE (a)-[:INCLUDES]-(c)
MERGE (a)-[:INCLUDES]-(d)
MERGE (e)-[:SAVED]-(a)
And it worked as expected.

Related

query with both MATCH and CREATE

I have 3 Nodes:
:User which has a unique id property
:Palette which has a unique name property
:Color which has a unique hex property
When a user saves a pallete I would like to:
create a new pallete if a palette with this name does not exist, and add a :CREATED relationship from the :User to the :Palette
create a :SAVED relationship from the :User to the :Palette if one does not exist
Afterwards I would like to delete all :INCLUDES relationships that this :Palette has to :Color nodes inside the database (in order to create new ones afterwards).
This is my query (I replaced the variables with hardcoded strings so it's easier to execute):
MATCH (u:User)
WHERE u.id = '4f3d1904'
MERGE (p:Palette {name: 'Test'})
ON CREATE
SET p.name = "Test"
MERGE (u)-[cr:CREATED]->(p)
MERGE (u)-[sa:SAVED]->(p)
MATCH (p:Palette {name: 'Test'})-[in:INCLUDES]->()
DELETE in
When running the query I get the following error:
WITH is required between MERGE and MATCH (line 8, column 1 (offset: 181))
"MATCH (p:Palette {name: 'Test'})-[in:INCLUDES]->()"
^
But if I add a WITH I get the following:
MATCH (u:User)
WHERE u.id = '4f3d1904'
MERGE (p:Palette {name: 'Test'})
ON CREATE
SET p.name = "Test"
MERGE (u)-[cr:CREATED]->(p)
MERGE (u)-[sa:SAVED]->(p)
WITH
MATCH (p:Palette {name: 'Test'})-[in:INCLUDES]->()
DELETE in
Invalid input ')': expected whitespace or a relationship pattern (line 9, column 32 (offset: 217))
"MATCH (p:Palette {name: 'Test'})-[in:INCLUDES]->()"
^
What am I doing wrong?
MERGE and MATCH stages (or MATCH and MATCH) require a WITH between them in order to use the result of the former in the latter.
In your case you can use the p that you already have like this:
...
WITH p
MATCH (p)-[in:INCLUDES]->()
DELETE in
So you won't need to find it again. without the WITH, it is like two different queries.

Return nodes that were deleted successfully

I am using the following query to delete nodes and the relationships:
MATCH (p:Post), (u:User)
WHERE
p.name IN ["Latest Post"]
AND u.id = 1
AND (p)-[:POST_OWNED_BY]->(u)
DETACH DELETE p
If I pass multiple post names, I would like to be able to return the names of the nodes that were successfully deleted.
I use neo4j manager usingExistingOrNewTransaction(session, tx, query) to commit the query.
Any reference or guide on how to return the successfully deleted nodes?
This should do it
MATCH (p:Post), (u:User)
WHERE
p.name IN ["Latest Post"]
AND u.id = 1
AND (p)-[:POST_OWNED_BY]->(u)
// make sure you store the p.name
WITH p, p.name AS deletedName
DETACH DELETE p
// return the name
RETURN deletedName

Optional nodes in a path?

I'm trying to write a query where I get the :LIKES relationships.
(:USER)
|
[:CREATED]
|
(:POST)<-[:LIKES]-(:USER)
|
[:RESHARED]
|
(:POST)<-[:LIKES]-(:USER)
I was trying something along the lines of:
MATCH (u:USER {name: "Lamoni"})-[:CREATED]-(p:POST)
OPTIONAL MATCH p<-[:LIKES]-(u2:USER)
OPTIONAL MATCH p<-[:RESHARED]-(p2:POST)<-[:LIKES]-(u3:USER)
Any ideas on an optimal way to do this and be able to order them by a property called created_at in a descending order?
Thanks!
If the POST structure always looks like this you can try:
// match the whole user-post-post path
MATCH (u:USER {name: "Lamoni"})-[:CREATED]-(p_direct:POST)-[:RESHARED]-(p_shared:Post)
WITH u, p_direct, p_shared
OPTIONAL MATCH (p_direct)<-[:LIKES]-(u2:USER)
OPTIONAL MATCH (p_shared)<-[:LIKES]-(u3:USER)
RETURN u.name, p_direct.xyz, collect(u2.name), p_shared.xyz, collect(u3.name)
If you just want all USERS that like a POST by a given USER (independent of the type of POST, created or shared) you can also collect all POST:
MATCH (u:USER {name: "Lamoni"})-[:CREATED|RESHARED*1..2]-(p:Post)
WITH u, p
OPTIONAL MATCH (p)<-[:LIKES]-(u2:USER)
WITH u.name, p, u2
ORDER BY u2.created_at
RETURN u.name, p, collect(u2.name)

Cypher to find similar nodes without repeating matches

I am new to cypher. I want to find similar nodes without repeating matches.
Sample data
CREATE (r1:Repository {id:"repository1"})
CREATE (r2:Repository {id:"repository2"})
CREATE (r3:Repository {id:"repository3"})
CREATE (a1:Actor {id: "actor1"})
CREATE (a2:Actor {id: "actor2"})
CREATE (a3:Actor {id: "actor3"})
CREATE (o1:Organization {id:"organization1"})
CREATE (o2:Organization {id:"organization2"})
MATCH (a:Repository {id:"repository1"}) MATCH (b:Actor {id: 'actor1'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository1"}) MATCH (b:Actor {id: 'actor2'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository1"}) MATCH (b:Actor {id: 'actor3'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository1"}) MATCH (b:Organization {id:
'organization1'}) CREATE (a)-[:IN_ORGANIZATION]->(b)
MATCH (a:Repository {id:"repository2"}) MATCH (b:Actor {id: 'actor1'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository2"}) MATCH (b:Actor {id: 'actor2'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository2"}) MATCH (b:Organization {id:
'organization1'}) CREATE (a)-[:IN_ORGANIZATION]->(b)
MATCH (a:Repository {id:"repository3"}) MATCH (b:Actor {id: 'actor3'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository3"}) MATCH (b:Organization {id:
'organization2'}) CREATE (a)-[:IN_ORGANIZATION]->(b)
Cypher
MATCH (a)-[r1:IS_ACTOR|IN_ORGANIZATION]->(match)<-
[r2:IS_ACTOR|IN_ORGANIZATION]-(b)
where not a.id = b.id with a,b,count(match) as count, collect (match.id) as
connections, collect (type(r1)) as rel1
return a.id,b.id,count,connections,rel1 order by count desc
Result
a.id b.id count connections rel1
repository2 repository1 3 actor1,actor2,organization1 IS_ACTOR, IS_ACTOR,IN_ORGANIZATION
repository1 repository2 3 actor1,actor2,organization1 IS_ACTOR, IS_ACTOR,IN_ORGANIZATION
repository3 repository1 1 actor3 IS_ACTOR
repository1 repository3 1 actor3 IS_ACTOR
How can I remove row #2 & #4 from the result?
Based on response to a similar question I tried using filter but I get syntax error (cypher below)
MATCH (a)-[r1:IS_ACTOR|IN_ORGANIZATION]->(match)<-
[r2:IS_ACTOR|IN_ORGANIZATION]-(b)
with filter(x in connections where x <> b.id)
where not a.id = b.id with a,b,count(match) as count, collect (match.id) as
connections, collect (type(r1)) as rel1
return a.id,b.id,count,connections,rel1 order by count desc
You match the path once from both sides, something that you can do to force only one of those paths to be returned. Compare the id's so you put a and b in a fixed order and avoid the other combo.
MATCH (a)-[r1:IS_ACTOR|IN_ORGANIZATION]->(match)
<-[r2:IS_ACTOR|IN_ORGANIZATION]-(b)
where id(a) > id(b)
with a,b,count(match) as count,
collect (match.id) as connections, collect (type(r1)) as rel1
return a.id,b.id,count,connections,rel1 order by count desc

Chaining result with "WITH" doesn't work when the subsequent query doesn't have matched result in Neo4j cypher query

For example, I created two linked nodes:
create (a:ACTOR {id: "a1", name: "bruce wellis"})
create (m:MOVIE {id: "m1", title: "die hardest"})
create (a)-[:ACTED_IN]->(m)
1. From this cypher query:
match (a:ACTOR {id: "a1"})
with a
optional match (m:MOVIE {id: "m1"})
set m += {
title: "die easier"
}
return a;
I can have result:
+-----------------------------------------+
| a |
+-----------------------------------------+
| Node[1000]{name:"bruce wellis",id:"a1"} |
+-----------------------------------------+
1 row
Properties set: 1
The query successfully returned the actor node.
2. (UPDATED) But if you make the match MOVIE subquery failed:
match (a:ACTOR {id: "a1"})
with a
optional match (m:MOVIE {id: "mm"})
set m += {
title: "die easier"
}
return a;
I got error:
CypherTypeException: Expected m to be a node or a relationship, but it was :`null`.
How to make the second query returning matched actor result?
A MATCH that fails to match anything will always return no rows.
So, in #2, since the second MATCH failed, it returns no rows.
You could use OPTIONAL MATCH in place of the second MATCH, and you should see results.
[EDITED]
For the Updated question, this (somewhat ugly) workaround should work:
MATCH (a:ACTOR {id: "a1"})
WITH a
OPTIONAL MATCH (m:MOVIE {id: "mm"})
WITH a, COLLECT(m) AS cm
FOREACH(m IN cm | SET m += {title: "die easier"})
RETURN a;

Resources