So far, we have used the neo4j.CollectTWithContext()
method to access results.
This method is the most convenient, and provides an element of type safety but it may not always be the best option.
Let’s look at some of the other methods that we can use to access the data returned to us by the Driver.
for
Loops
The result
object returned by session.Run()
and tx.Run()
is an iterable object known as a cursor.
Individual records are available in the cursor until they are consumed.
You can check that there are results remaining in the cursor by calling the .Next()
method.
While the .Next()
returns true
, you can call the .Record()
method to get the next record.
// .Next() returns false upon error
for result.Next() {
record := result.Record()
handleRecord(record)
}
// Err returns the error that caused Next to return false
if err = result.Err(); err != nil {
handleError(err)
}
It is important to verify the value returned by the Err()
is false
after calling the .Next()
method to find out whether the the last result is the final result witin the stream, or an error has occurred to cause the end of result consumption.
NextRecord()
Alternatively, you can use the NextRecord()
method which has the same outcome with less code.
for result.NextRecord(&record) {
fmf.Println(record.Keys)
}
Getting the only result with Single()
If you are expecting a single result, you can call the Single()
method to access the first and only result.
// Get the first and only result from the stream.
first, err := record.Single()
If the result stream contains zero or more than one records, an error is returned.
Get all remaining results with Collect()
The Collect()
method fetches all remaining records and returns them as an array.
remaining, remainingErr := result.Collect()
Consume remaining results with Consume()
Calling the Consume()
method will discard any remaining records from the stream and return a ResultSummary
object which holds information about the statement execution, including database information, execution time and in the case of a write query, statistics on changes made to the database as a result of the statement execution.
summary := result.Consume()
// Time in milliseconds before receiving the first result
fmt.Println(summary.ResultAvailableAfter())
// Time in milliseconds once the final result was consumed
fmt.Println(summary.ResultConsumedAfter())
Exploring Records
The record
variable above provides an interface to retrieve individual values.
Take the example above, each record will contain information on :Movie
and :Person
nodes, and the :ACTED_IN
relationship.
To access the keys available in each record, you can use the .Keys
property.
This is an array of strings.
fmt.Println(record.Keys) // ['p', 'r', 'm']
To access these values, we can either use the index of the key above, or the alias specified in the RETURN
portion of the Cypher statement.
// Access a value by its index
fmt.Println(record.Values[0].(neo4j.Node)) // The Person node
// Access a value by its alias
movie, _ := record.Get("movie")
movieNode := movie.(neo4j.Node)
fmt.Println(movieNode) // The Movie node
Check Your Understanding
1. Consuming the only Result left
Which method would you use to consume the only record left in a result?
-
❏
result.First()
-
❏
result[0]
-
❏
result.Get(0)
-
✓
result.Single()
Hint
You would often use this method when expecting a single record from the database.
Solution
The answer is result.Single()
.
2. Query Statistics
Which method would you use to obtain statistics on a result of a write query?
-
✓
result.Consume()
-
❏
result.Info()
-
❏
result.Summary()
Hint
To obtain query statistics, you must consume the results.
Solution
The answer is result.Consume()
.
3. Get all Remaining Records
Which of the following examples will allow you to extract an array of any remaining results?
-
❏
result.All()
-
✓
result.Collect()
-
❏
result.Consume()
-
❏
result.Remaining()
Hint
In Neo4j, we call a set of results a collection.
Solution
The answer is result.Collect()
.
Lesson Summary
You now have all of the information required to send Cypher queries to Neo4j and consume the results.
Next, we will look at the Neo4j Type System and some of the considerations that you need to make when working with values coming from Neo4j in your Go application.