Using the WITH clause to separate READ and WRITE queries

Hello Neo4jers,

Back again!

The Cypher manual says -

WITH is also used to separate reading from updating of the graph. Every part of a query must be either read-only or write-only. When going from a writing part to a reading part, the switch must be done with a WITH clause.

For instance, as in the query below where there is a MATCH after a MERGE, we see a WITH -
MERGE (a:Actor {name: 'Michael Caine'})
SET a.born = 1933
WITH a
MATCH (p)
WHERE p.name = 'Michael Caine'
RETURN p

I am wondering why this is so. If this is explained in some documentation, I would greatly appreciate it if you could direct me to it.

Thanks!

Hi Poormina,

shortly explained: WITH forwards the first results (or part of it) not to screen (this would be RETURN) but to a second query which will reuse those results (This is the primary idea of WITH).

The given query makes sense in the way you told "separate writing from querying", but ...
it is some kind of special case because an "a" is forwarded, but not used in the second part. Which mean this WITH is only a separator to have 2 queries in one shot.

I presume the given query has only been build in order to document the separation of the querying of read and the querying of write. And therefore reduced to something which is hardly understandable: the returning of a writing query (withount "requyiring"!) is also allowed (but not to encourage):

MERGE (a:Actor {name: 'Michael Caine'})
SET a.born = 1933
RETURN a.name, a.born

This might work in an interactiv neo4j browser, but over an encoding with API, it will be better to create 2 queries, and especially checking the succes of the writing before sending the reading query.

Cheers

Thank you @Benoit_d ! Indeed, I missed the part where 'a' is not even being used downstream :slight_smile: that just makes this stranger and also throws a wrench into a possible explanation (see below). With the MERGE and SET example you have shown, they are both 'updates' so maybe that's why we don't need to re-query? Also, I know MERGE places a lock, I am not sure at what level, so we could potentially do as many updates as we want but to the objects identified in the MERGE?

I was thinking about this morning and the WITH made sense. If a MERGE were to update certain nodes, these updates will not be visible unless we do a fresh MATCH with a pattern. I can imagine this would be a costly operation in large graphs if we needed to do further operations with the objects i.e. nodes/relationships/properties which were just updated. With the 'WITH', this need to perform a MATCH to retrieve the updated objects is eliminated and since we already have this set of objects in the variables passed down through WITH, we can focus on performing just the subsequent operations we had intended.

However, with the example I specified (which came right out of the training documentation), I am not sure anymore! :slight_smile:

Better explanation here - Querying, updating and administering - Neo4j Cypher Manual

Keep in mind that MERGE is like a MATCH, where if no results are found, it will do a CREATE under the hood. The variables bound to the MERGE pattern are therefore guaranteed to exist afterward, without needing to re-MATCH.

Locks are taken for the entire duration of the transaction. Within the transaction itself (unless there are any procedures or elements of the query that end up spinning off separate transactions) there will be no lock contention among the locks the transaction takes (they are treated as reentrant locks). So locks are not going to be released mid-way through any query.

Personally I don't really care for the description that a WITH separates read from write elements of a query, I don't really find that understanding very useful myself, if the compiler yells at you to add a WITH between some clauses, do so, but WITH serves several more important purposes:

It controls the scope of what variables are preserved from one part of the query to the next. If a variable is not included in a WITH clause, then you cannot reference that variable later (worse, if you do so by accident, it will be treated as a brand new variable, and not the graph element it was previously bound to).

It allows invocation of functions, and other operations (arithmetic, concatenation, etc) as well as the introduction of new variables.

1 Like

Hi,
The MERGE command adds a new node to the database only if it does not already exist.
Thanks