Installation

In the Cypher Fundamentals course, we cover how to query Neo4j using a language called Cypher. To execute a Cypher statement against a Neo4j database you will use an object called a Driver.

To connect to and query Neo4j from within a Go application, you use the Neo4j Go Driver.

Installing the Driver

The Neo4j Go Driver is available through pkg.go.dev. The Neo4j Go Driver can be installed using the go get command.

sh
Installing the neo4j-go-driver dependency
go get -u github.com/neo4j/neo4j-go-driver/v5

Importing the Library

The github.com/neo4j/neo4j-go-driver package exports a neo4j object which contains several helper functions for interacting with Neo4j.

go
Importing The Driver
// Import the driver
import (
	"context"
	"fmt"
	"time"

	. "github.com/neo4j-graphacademy/neoflix/pkg/shared"
	"github.com/neo4j/neo4j-go-driver/v5/neo4j"
)

Creating a Driver Instance

To create a new instance of the driver, you can use the neo4j.NewDriverWithContext() function provided by the driver library, which accepts neo4j credentials and returns a new driver object.

go
Creating a Driver Instance
// Create a Driver Instance
ctx := context.Background()
driver, err := neo4j.NewDriverWithContext(
	"neo4j+s://dbhash.databases.neo4j.io",    // (1)
	neo4j.BasicAuth("neo4j", "letmein!", ""), // (2)
)

The function expects two arguments;

  1. A Connection URI - for example, neo4j://localhost:7687 or neo4j+s://dbhash.databases.neo4j.io

  2. An authentication token

Authentication Types

Neo4j supports four authentication methods, basic authentication (e.g. username and password or LDAP), a base64 encoded Bearer token, a Kerberos token, or a custom authentication token. For more information on these options, visit Authentication and Authorization.

Verifying Connectivity

You can verify that the connection details used during driver instantiation are correct by calling the driver.VerifyConnectivity() method.

This function returns an error with the Neo.ClientError.Security.Unauthorized code if the provided credentials are incorrect.

go
Verify Connectivity
// Verify Connectivity
PanicOnErr(driver.VerifyConnectivity(ctx))

Sessions

From the driver object, you will open one or more sessions. A session is a client-side abstraction that borrows underlying TCP connections from a connection pool held by the Driver and uses them to communicate with Neo4j.

Sessions should be considered lightweight and disposable and can be opened and closed at will. To close a session, call the .Close() method. This will release any underlying TCP connections held by the session object.

go
Session Lifecycle
// Open a new Session
session := driver.NewSession(ctx, neo4j.SessionConfig{})

You can implicitly defer the closing of each session object, which will release any underlying TCP connections held by the session object once the surrounding context has completed.

go
Defer Session Closure
defer PanicOnClosureError(ctx, driver)
defer PanicOnClosureError(ctx, session)

Running a Sample Query

To run a one-off Cypher query, you can use the session.Run() method.

go
Running a One-off Query
// Execute a Cypher statement in an auto-commit transaction
result, err := session.Run(
	ctx, // (1)
	`
	MATCH (p:Person)-[:DIRECTED]->(:Movie {title: $title})
	RETURN p
	`, // (2)
	map[string]any{"title": "The Matrix"}, // (3)
	func(txConfig *neo4j.TransactionConfig) {
		txConfig.Timeout = 3 * time.Second // (4)
	},
)
PanicOnErr(err)

The method accepts four arguments:

  1. The execution context.

  2. A string to represent a Cypher statement

  3. An optional map representing query parameters (prefixed in Cypher with $).

  4. Optional, a map containing transaction config.

For one-off queries only

If there are any transient errors when running a query, the driver will not attempt to retry a query when using session.Run(). For this reason, these should only be used for one-off queries and not in production.

Processing Results

The result value in the code sample above will be an implementation of the ResultWithContext interface. This can be used in conjunction with the neo4j.CollectTWithContext() function to access the values returned by Neo4j. The function expects a context object, a ResultWithContext object, and an accessor function.

The function is passed one argument, an instance of neo4j.Record, which can be passed to the neo4j.GetRecordValue() method.

go
Accessing Results
// Get all Person nodes
people, err := neo4j.CollectTWithContext[neo4j.Node](ctx, result,
	func(record *neo4j.Record) (neo4j.Node, error) {
		person, _, err := neo4j.GetRecordValue[neo4j.Node](record, "p")
		return person, err
	})
PanicOnErr(err)
fmt.Println(people)

In the code sample above, the p value is extracted from each node using the neo4j.GetRecordValue() function, which is assigned to the person variable. In this instance, p refers to a Neo4j Node, which is hydrated into an instance of the neo4j.Node interface.

Should the p key not exist on the record or any other error occurs while trying to retrieve the value, the subsequent error will be assigned to the err variable.

We will cover result processing in more detail in Lesson 3: Read and Write Transactions.

Closing the Driver

The Driver provides a .Close() method, which closes any open sessions, disconnect all servers and release any resources held by the driver.

go
Running a One-off Query
// Close the driver to release any resources
driver.Close(ctx)

Check Your Understanding

What symbol do you need to import to use the Neo4j Go Driver?

  • neo4j

  • go.dev/neo4j/driver

  • github.com/neo4j/neo4j-go-driver/v5/neo4j

  • neo4j-go-driver

Hint

You can search for the package on pkg.go.dev.

Solution

The symbol you need to import is github.com/neo4j/neo4j-go-driver/v5/neo4j.

Summary

In this lesson, you learned the basics of the Neo4j Go Driver, how to install the dependency, create a new driver instance and execute a sample query.

In the next lesson, you will use this knowledge to query a Neo4j Sandbox instance.