0

I would like to update node property more than one time (node). How does the cypher query look like?

For example, we can update node property individually by running the below cypher query

MATCH (a:Span {id:"A"})
SET a.name = "checkout";

and

MATCH (b:Span {id:"B"})
SET b.name = "login";

separately.

But is there way to run the update together? I tried

MATCH (a:Span {id:"A"})
SET a.name = "checkout"
MATCH (b:Span {id:"B"})
SET b.name = "login";

Neo4j just throws "Neo.ClientError.Statement.SyntaxError" and does not work.

David Makogon
  • 69,407
  • 21
  • 141
  • 189
TripleH
  • 447
  • 7
  • 16

1 Answers1

2

Your query:

MATCH (a:Span {id:"A"})
SET a.name = "checkout"
MATCH (b:Span {id:"B"})
SET b.name = "login"

is not legal because "write" clauses like SET cannot be followed by a "read" clause like MATCH without an intervening WITH clause.

But this query:

MATCH (a:Span {id:"A"})
SET a.name = "checkout"
WITH 0 AS ignored
MATCH (b:Span {id:"B"})
SET b.name = "login";

is not efficient if there can be multiple "A" nodes. For example, if there are 50 "A" nodes, then every "B" node will have its name set 50 times.

To avoid assigning the same value to the same property multiple times, you can use aggregation to reduce N "A" rows down to just 1 row before matching "B":

MATCH (a:Span {id:"A"})
SET a.name = "checkout"
WITH COUNT(*) AS ignored
MATCH (b:Span {id:"B"})
SET b.name = "login";

Or you can use a unit subquery, which "does not change the number of rows of the enclosing query." For example, you can do this:

CALL {
  MATCH (a:Span {id:"A"})
  SET a.name = "checkout"
}
MATCH (a:Span {id:"B"})
SET a.name = "login";
cybersam
  • 63,203
  • 6
  • 53
  • 76
  • I thought the Cartesian product was only built for queries such as `MATCH (a), (b)`, but _not_ for `MATCH (a) MATCH (b)`. https://stackoverflow.com/a/33354771/112968 – can you elaborate on that? – knittl Apr 27 '23 at 10:36
  • Thank you for the answer. The query with `CALL {.... }` works. But what if I have node id: "C", "D", .....etc? Do we have Cypher query in more iterative way to update? – TripleH Apr 27 '23 at 14:14
  • @knitti. The answer your referenced has a `WITH` clause between the 2 `MATCH` causes to avoid the cartesian product. But since the Cypher planner implementation can change with every neo4j version, you should use [PROFILE] to compare the operations generated for 2 alternate Cypher scripts. – cybersam May 01 '23 at 15:23
  • @TripleH You can put each `MATCH/SET` pair in its own `CALL` subquery. If you are passing the Cypher code in a string, you can generate the Cypher for each subquery. On neo4j, there are many [APOC procedures](https://neo4j.com/docs/apoc/5/cypher-execution/) that are useful for processing dynamically generated Cypher. – cybersam May 01 '23 at 15:36