Transaction functions

You have built an application that streams the results of a long-running Cypher statement to the client.

You have written a transaction function called getCheapestFlights to execute a read query within a transaction.

View the getCheapestFlights function
go
/*
Return the cheapest flights between the origin and
destination airports on a given date.
*/
func getCheapestFlights(tx neo4j.ManagedTransaction, date, origin, destination string) ([]any, error) {
    result, err := tx.Run(ctx, `
        MATCH (origin:Airport)<-[:ORIGIN]-(f:Flight)-[:DESTINATION]->(destination:Airport),
            (f)-[:OPERATED_BY]->(operator:Airline)
        WHERE origin.name = $origin AND destination.name = $destination AND f.date = $date
        RETURN f.price AS price, operator.name AS operator
    `, map[string]any{"date": date, "origin": origin, "destination": destination})

    if err != nil {
        return nil, err
    }

    var flights []any
    for result.Next(ctx) {
        record := result.Record()
        price, _ := record.Get("price")
        operator, _ := record.Get("operator")
        flights = append(flights, map[string]any{"price": price, "operator": operator})
    }

    return flights, nil
}

The application then uses an external function called sendToUI to send the results to the client.

Read transactions

Select the correct function to execute the Cypher statement in a read transaction and stream the results to the client as soon as they are available.

go
import (
    "api"
    "log"
)

session := driver.NewSession(ctx, neo4j.SessionConfig{})
defer session.Close(ctx)

res, err := session./*select:ExecuteRead*/(
    ctx,
    func(tx neo4j.ManagedTransaction) (any, error) {
        return getCheapestFlights(tx, "2024-01-01", "LAX", "SFO")
    },
)

if err != nil {
    log.Fatal(err)
}

flights := res.([]any)
for _, row := range flights {
    sendToUI(row)
}
  • ❏ Run(

  • ✓ ExecuteRead(

  • ❏ ExecuteWrite(

  • ❏ ReadAsync(

Hint

When reading data from Neo4j, use ExecuteRead() to run a read transaction. This ensures that the transaction is properly managed and allows for streaming results back to the client.

Solution

The correct answer is ExecuteRead().

ExecuteRead() is the recommended method for running read transactions in Neo4j. The function handles transaction management automatically and allows for streaming results as they become available.

go
session := driver.NewSession(ctx, neo4j.SessionConfig{})
defer session.Close(ctx)

res, err := session.ExecuteRead(
    ctx,
    func(tx neo4j.ManagedTransaction) (any, error) {
        return getCheapestFlights(tx, "2024-01-01", "LAX", "SFO")
    },
)

if err != nil {
    log.Fatal(err)
}

flights := res.([]any)
for _, row := range flights {
    sendToUI(row)
}

The other options are incorrect because:

  • Run() is not a method on the session object

  • ExecuteWrite() is for write transactions only

  • ReadAsync() is not a valid method for the session object

Summary

In this lesson, you demonstrated how to execute a read transaction using the ExecuteRead() method. The method handles transaction management automatically and allows for streaming results as they become available.

The ExecuteRead() method is the recommended way to run read transactions as it:

  • Automatically handles transaction management

  • Enables streaming of results as they become available

  • Ensures proper transaction lifecycle and resource cleanup

Consuming results

Remember that the results must be consumed within the transaction function. Once the transaction is completed, the results are no longer available.

Chatbot

How can I help you today?