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
/*
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.
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.
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.