Match if node exists and set new property

I'm trying to write a query where if a node exists sets a new property with a specific value, if not, it creates a new node
I wrote this, but it doesn't work:

MATCH (n:User_friend)
RETURN 
CASE WHEN n.name='name surname' then set n.phone_number=123456789
ELSE CREATE node (n:User friend { n.phone_number: 123456789})
END

I have read the documents about CASE here, but obviously I wasn't able to understand it.

CASE can only be used for expressions, you cannot use it to execute conditional Cypher, so SET and CREATE can't be used within.

I think MERGE might be what you're looking for, as it has ON CREATE and ON MATCH clauses that execute depending on if the MERGE resulted in matching to an existing node or creating a new one.

That said, this looks like a type of case that MERGE may not cover, since the property that you're attempting to check/lookup by (name) isn't the one that you want to set if creating the new node (phone_number).

We might be able to do this with a bit of clever aggregation:

MATCH (n:User_friend)
WHERE n.name='name surname'
SET n.phone_number=123456789
WITH count(n) as nodesAltered
WHERE nodesAltered = 0
CREATE (n:User_friend {phone_number: 123456789})

Usually, when rows go to 0 (due to filtering or not finding something that meets a MATCH) everything else becomes no-op, since operations execute per row. But when we aggregate, we can turn 0 rows back to 1. In this case, we're doing a count() of n, which will be 0 if the MATCH didn't find anything, and a non-zero otherwise. We can use a WHERE clause after this to filter, so only in the case that no node was matched to and altered will we create a new node.

1 Like

It's so simple and yet so ingenious. I hadn't thought about it, because I had been reluctant to use CASE. Thank you very much