Difference between session.run and session.readTransaction or session.writeTransaction

In Javascript driver, what is the difference between running Cypher queries using session.run() and session.readTransaction((tx) => {tx.run()}) or session.writeTransaction((tx) => {tx.run()}) ?

1 Like

This is a great question, a common one, and a difference with big consequences, so let's break it down.

Session.run is the simplest, easiest form, something called an "autocommit transaction". While it's an easy way to get started, it's not recommended in production. You should instead use readTransaction and writeTransaction, for a bunch of reasons.

  1. You should signal to the driver whether you're trying to read or write. In Neo4j clustered setups, when you're using the bolt+routing:// or neo4j:// schemes, this tells the driver how to appropriately route your query to the right machine. If you want to know more about this topic, have a look at Querying Neo4j Clusters.

  2. With session.run, note you're passing a cypher query. With the other two, you're passing a function that performs the work of the transaction. This is a critical difference. One lets you run a single query. In the other, you might have a function that does a number of different sub-queries, all of which you want to wrap. up into a single overall TX that either succeeds or fails. See (Transaction Management for much more detail). In complex setups this comes up a lot that doing a particular update to your system might take 3 cypher queries, not 1. And you don't want to "partially succeed" you want either all 3 to go through, or none. To do something like that you want a tx work function.

Bottom line -- prefer the use of readTransaction and writeTransaction. Get into that habit and you'll always be in good shape.

2 Likes

Thanks for the clarification, David!
So, if I have a bunch of queries that should be performed sequentially (dependent queries) then how should I write them in a transaction so that the second one is performed only when the first one is successfully completed?
I'd highly appreciate it if you could direct me to any such detailed examples to understand and implement the best-practices in this regard.

Thank you,
Sheekha

1 Like

Check the "Transactions Functions" documentation in the driver manual, they have examples in all supported languages.

https://neo4j.com/docs/driver-manual/1.7/sessions-transactions/#driver-transactions-transaction-functions

Specifically, you can use tx.run to do the things inside of the transaction sequentially that you need.

1 Like

I tried the following code and I couldn't get results from the database -

session.readTransaction((transaction) => {
var getUserProfileResult = transaction.run("match (u:user{id:'" + userid + "'}) return u");
result = { ...result, userProfile: getUserProfileResult.summary }
var getUserLanguagesResult = transaction.run("match (u:user{id:'" + userid + "'})-[k:knows]->(v) return u,k,v");
result = { ...result, languages: getUserLanguagesResult.summary };
var getUserFriendsResult = transaction.run("match (u:user{id:'" + userid + "'})-[f:friendOf]->(v) return u,f,v");
result = { ...result, friends: getUserFriendsResult.summary };
console.log('result is ', result);
return result
}).then(result => {
return res.json({ result });
}).catch(function(error) {
console.log("get user error: " + error);
}).finally((result) => {
session.close();
});

I get 'undefined' when I print the result.summary or result.records.
Could you help me figure out what am I doing wrong here?