title: Is this the proper way to write a multi-statement transaction with Neo4j?
body: <p>I am having a hard time interpretting the documentation from Neo4j about transactions. Their documentation seems to indicate preference to doing it <em>this</em> way rather than explicitly declaring <code>tx.commit()</code> and <code>tx.rollback()</code>.</p>
  
  <p>Does this look best practice with respect to multi-statement transactions and <code>neo4j-driver</code>?</p>
  
  <pre><code>const register = async (container, user) =&gt; {
      const session = driver.session()
      const timestamp = Date.now()
  
      const saltRounds = 10
      const pwd = await utils.bcrypt.hash(user.password, saltRounds)
  
      try {
          //Start registration transaction
              const registerUser = session.writeTransaction(async (transaction) =&gt; {
              const initialCommit = await transaction
                  .run(`
                      CREATE (p:Person {
                          email: '${user.email}',
                          tel: '${user.tel}',
                          pwd: '${pwd}',
                          created: '${timestamp}'
                      })
                      RETURN p AS Person
                  `)
  
              const initialResult = initialCommit.records
                  .map((x) =&gt; {
                      return {
                          id: x.get('Person').identity.low,
                          created: x.get('Person').properties.created
                      }
                  })
                  .shift()
  
              //Generate serial
              const data = `${initialResult.id}${initialResult.created}`
              const serial = crypto.sha256(data)
  
              const finalCommit = await transaction
                  .run(`
                      MATCH (p:Person)
                      WHERE p.email = '${user.email}'
                      SET p.serialNumber = '${serial}'
                      RETURN p AS Person
                  `)
  
              const finalResult = finalCommit.records
                  .map((x) =&gt; {
                      return {
                          serialNumber: x.get('Person').properties.serialNumber,
                          email: x.get('Person').properties.email,
                          tel: x.get('Person').properties.tel
                      }
                  })
                  .shift()
  
              //Merge both results for complete person data
              return Object.assign({}, initialResult, finalResult)
          })
  
          //Commit or rollback transaction
          return registerUser
              .then((commit) =&gt; {
                  session.close()
                  return commit
              })
              .catch((rollback) =&gt; {
                  console.log(`Transaction problem: ${JSON.stringify(rollback, null, 2)}`)
                  throw [`reg1`]
              })
      } catch (error) {
      session.close()
          throw error
      }
  }
  </code></pre>
  
  <blockquote>
    <p>Here is the reduced version of the logic:</p>
  </blockquote>
  
  <pre><code>const register = (user) =&gt; {
      const session = driver.session()
      const performTransaction = session.writeTransaction(async (tx) =&gt; {
  
          const statementOne = await tx.run(queryOne)
          const resultOne = statementOne.records.map((x) =&gt; x.get('node')).slice()
  
          // Do some work that uses data from statementOne
  
          const statementTwo = await tx.run(queryTwo)
          const resultTwo = statementTwo.records.map((x) =&gt; x.get('node')).slice()
  
          // Do final processing
  
          return finalResult
      })
  
      return performTransaction.then((commit) =&gt; {
             session.close()
             return commit
      }).catch((rollback) =&gt; {
              throw rollback
      })
  }
  </code></pre>
  
  <p>Neo4j experts, is the above code the correct use of <code>neo4j-driver</code> ?</p>
  
  <blockquote>
    <p>I would rather do this because its more linear and synchronous:</p>
  </blockquote>
  
  <pre><code>const register = (user) =&gt; {
      const session = driver.session()
      const tx = session.beginTransaction()
  
      const statementOne = await tx.run(queryOne)
      const resultOne = statementOne.records.map((x) =&gt; x.get('node')).slice()
  
      // Do some work that uses data from statementOne
  
      const statementTwo = await tx.run(queryTwo)
      const resultTwo = statementTwo.records.map((x) =&gt; x.get('node')).slice()
  
      // Do final processing
      const finalResult = { obj1, ...obj2 }
      let success = true
  
     if (success) {
         tx.commit()
         session.close()
         return finalResult
     } else {
         tx.rollback()
         session.close()
         return false
     }
  }
  </code></pre>
  
  <p>I'm sorry for the long post, but I cannot find any references anywhere, so the community needs this data.</p>