neo4j

package
v5.8.1-10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2023 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package neo4j provides required functionality to connect and execute statements against a Neo4j Database.

Package neo4j provides required functionality to connect and execute statements against a Neo4j Database.

Index

Examples

Constants

View Source
const (
	// ERROR is the level that error messages are written
	ERROR LogLevel = 1
	// WARNING is the level that warning messages are written
	WARNING = 2
	// INFO is the level that info messages are written
	INFO = 3
	// DEBUG is the level that debug messages are written
	DEBUG = 4
)
View Source
const FetchAll = -1

FetchAll turns off fetching records in batches.

View Source
const FetchDefault = 0

FetchDefault lets the driver decide fetch size

View Source
const UserAgent = "Go Driver/5.8.1"

Variables

This section is empty.

Functions

func BookmarksToRawValues

func BookmarksToRawValues(bookmarks Bookmarks) []string

BookmarksToRawValues exposes the raw server-side bookmarks. You should not need to use this method unless you want to serialize bookmarks. See Session.LastBookmarks and CombineBookmarks for alternatives.

func CollectT deprecated

func CollectT[T any](result Result, mapper func(*Record) (T, error)) ([]T, error)

CollectT maps the records to a slice of T with the provided mapper function. It relies on Result.Collect and propagate its error, if any.

Deprecated: use CollectTWithContext instead (the entry point of context-aware APIs is NewDriverWithContext)

func CollectTWithContext

func CollectTWithContext[T any](ctx context.Context, result ResultWithContext, mapper func(*Record) (T, error)) ([]T, error)

CollectTWithContext maps the records to a slice of T with the provided mapper function. It relies on ResultWithContext.Collect and propagate its error, if any. It accepts a context.Context, which may be canceled or carry a deadline, to control the overall record fetching execution time.

func ConsoleBoltLogger

func ConsoleBoltLogger() *log.ConsoleBoltLogger

func ConsoleLogger

func ConsoleLogger(level LogLevel) *log.Console

func ExecuteQuery

func ExecuteQuery[T any](
	ctx context.Context,
	driver DriverWithContext,
	query string,
	parameters map[string]any,
	newResultTransformer func() ResultTransformer[T],
	settings ...ExecuteQueryConfigurationOption) (res T, err error)

ExecuteQuery runs the specified query with its parameters and returns the query result, transformed by the specified ResultTransformer function.

result, err := ExecuteQuery[*EagerResult](ctx, driver, query, params, EagerResultTransformer)

Passing a nil ResultTransformer function is invalid and will return an error.

Likewise, passing a function that returns a nil ResultTransformer is invalid and will return an error.

ExecuteQuery runs the query in a single explicit, retryable transaction within a session entirely managed by the driver.

Retries occur in the same conditions as when calling SessionWithContext.ExecuteRead and SessionWithContext.ExecuteWrite.

Because it is an explicit transaction from the server point of view, Cypher queries using "CALL {} IN TRANSACTIONS" or the older "USING PERIODIC COMMIT" construct will not work (call SessionWithContext.Run for these).

Specific settings can be configured via configuration callbacks. Built-in callbacks are provided such as:

	neo4j.ExecuteQueryWithDatabase
	neo4j.ExecuteQueryWithWritersRouting
 ...

see neo4j.ExecuteQueryConfiguration for all possibilities.

These built-in callbacks can be used and combined as follows:

ExecuteQuery[T](ctx, driver, query, params, transformerFunc,
	neo4j.ExecuteQueryWithDatabase("my-db"),
	neo4j.ExecuteQueryWithWritersRouting())

For complete control over the configuration, you can also define your own callback:

ExecuteQuery[T](ctx, driver, query, params, transformerFunc, func(config *neo4j.ExecuteQueryConfiguration) {
	config.Database = "my-db"
	config.RoutingControl = neo4j.Write
	config.ImpersonatedUser = "selda_bağcan"
})

ExecuteQuery causal consistency is guaranteed by default across different successful calls to ExecuteQuery targeting the same database. In other words, a successful read query run by ExecuteQuery is guaranteed to be able to read results created from a previous successful write query run by ExecuteQuery on the same database. This is achieved through the use of bookmarks, managed by a default neo4j.BookmarkManager instance. This default BookmarkManager instance can be retrieved with DriverWithContext.DefaultExecuteQueryBookmarkManager. Such a consistency guarantee is *not* maintained between ExecuteQuery calls and the lower-level neo4j.SessionWithContext API calls, unless sessions are explicitly configured with the same bookmark manager. That guarantee may also break if a custom implementation of neo4j.BookmarkManager is provided via for instance the built-in callback neo4j.ExecuteQueryWithBookmarkManager. You can disable bookmark management by passing the neo4j.ExecuteQueryWithoutBookmarkManager callback to ExecuteQuery.

The equivalent functionality of ExecuteQuery can be replicated with pre-existing APIs as follows:

 // all the error handling bits have been omitted for brevity (do not do this in production!)
	session := driver.NewSession(ctx, neo4j.SessionConfig{
		DatabaseName:     "<DATABASE>",
		ImpersonatedUser: "<USER>",
		BookmarkManager:  bookmarkManager,
	})
	defer handleClose(ctx, session)
	// session.ExecuteRead is called if the routing is set to neo4j.Read
	result, _ := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (any, error) {
		result, _ := tx.Run(ctx, "<CYPHER>", parameters)
		records, _ := result.Collect(ctx) // real implementation does not use Collect
		keys, _ := result.Keys()
		summary, _ := result.Consume(ctx)
		return &neo4j.EagerResult{
			Keys:    keys,
			Records: records,
			Summary: summary,
		}, nil
	})
	eagerResult := result.(*neo4j.EagerResult)
	// do something with eagerResult

The available ResultTransformer implementation, EagerResultTransformer, computes an *EagerResult. As the latter's name suggests, this is not optimal when the result is made from a large number of records. In that situation, it is advised to create a custom implementation of ResultTransformer APIs, which do not require keeping all records in memory.

The provided ResultTransformer function may be called several times since ExecuteQuery relies on transaction functions. Since ResultTransformer implementations are inherently stateful, the function must return a new ResultTransformer instance every time it is called.

Contexts terminating too early negatively affect connection pooling and degrade the driver performance.

Example
query := "RETURN $value AS val"
params := map[string]any{"value": 42}
eagerResult, err := ExecuteQuery[*EagerResult](ctx, myDriver, query, params, EagerResultTransformer)
handleError(err)

// iterate over all keys (here it's only "val")
for _, key := range eagerResult.Keys {
	fmt.Println(key)
}
// iterate over all records (here it's only {"val": 42})
for _, record := range eagerResult.Records {
	rawValue, _ := record.Get("value")
	fmt.Println(rawValue.(int64))
}
// consume information from the query execution summary
summary := eagerResult.Summary
fmt.Printf("Hit database is: %s\n", summary.Database().Name())
Output:

Example (DefaultBookmarkManagerExplicitReuse)
query := "CREATE (n:Example)"
params := map[string]any{"value": 42}
_, err := ExecuteQuery[*EagerResult](
	ctx, myDriver, query, params, EagerResultTransformer, ExecuteQueryWithWritersRouting())
handleError(err)

// retrieve the default bookmark manager used by the previous call (since there was no bookmark manager explicitly
// configured)
bookmarkManager := myDriver.ExecuteQueryBookmarkManager()
session := myDriver.NewSession(ctx, SessionConfig{BookmarkManager: bookmarkManager})

// the following transaction function is guaranteed to see the result of the previous query
// since the session uses the same bookmark manager as the previous ExecuteQuery call and targets the same
// (default) database
count, err := session.ExecuteRead(ctx, func(tx ManagedTransaction) (any, error) {
	eagerResult, err := tx.Run(ctx, "MATCH (n:Example) RETURN count(n) AS count", nil)
	if err != nil {
		return nil, err
	}
	record, err := eagerResult.Single(ctx)
	if err != nil {
		return nil, err
	}
	count, _ := record.Get("count")
	return count.(int64), nil
})
handleError(err)
fmt.Println(count)
Output:

Example (SelfCausalConsistency)
query := "CREATE (n:Example)"
params := map[string]any{"value": 42}
_, err := ExecuteQuery[*EagerResult](
	ctx, myDriver, query, params, EagerResultTransformer, ExecuteQueryWithWritersRouting())
handleError(err)

// assuming an initial empty database, the following query should return 1
// indeed, causal consistency is guaranteed by default, which subsequent ExecuteQuery calls can read the writes of
// previous ExecuteQuery calls targeting the same database
query = "MATCH (n:Example) RETURN count(n) AS count"
eagerResult, err := ExecuteQuery[*EagerResult](
	ctx, myDriver, query, nil, EagerResultTransformer, ExecuteQueryWithReadersRouting())
handleError(err)

// there should be a single record
recordCount := len(eagerResult.Records)
if recordCount != 1 {
	handleError(fmt.Errorf("expected a single record, got: %d", recordCount))
}
// the record should be {"count": 1}
if rawCount, found := eagerResult.Records[0].Get("val"); !found || rawCount.(int64) != 1 {
	handleError(fmt.Errorf("expected count of 1, got: %d", rawCount.(int64)))
}
Output:

func ExecuteRead

func ExecuteRead[T any](ctx context.Context, session SessionWithContext,
	work ManagedTransactionWorkT[T],
	configurers ...func(config *TransactionConfig)) (T, error)

ExecuteRead executes the given unit of work in a read transaction with retry logic in place, via the provided session.

This is the generic variant of SessionWithContext.ExecuteRead.

If an error occurs, the zero value of T is returned.

Example
package main

import (
	"context"
	"fmt"
	"github.com/SGNL-ai/neo4j-go-driver/v5/neo4j"
	"os"
)

type Person struct {
	Name  string
	Login string
}

func (p *Person) String() string {
	return fmt.Sprintf("name: %s, login: %s", p.Name, p.Login)
}

func (p *Person) asNodeProps() map[string]any {
	return map[string]any{
		"name":  p.Name,
		"login": p.Login,
	}
}

func main() {
	ctx := context.Background()
	driver, err := createDriver()
	handleError(err)
	defer handleClose(ctx, driver)
	session := driver.NewSession(ctx, neo4j.SessionConfig{})
	defer handleClose(ctx, session)

	personLogin := readPersonLoginFromRequest()

	// with neo4j.ExecuteRead, `person` is guaranteed to be of the declared type if no error occurs
	// note: if an error occurs, the default value (sometimes called "zero value") of the type is returned
	person, err := neo4j.ExecuteRead[*Person](ctx, session, func(tx neo4j.ManagedTransaction) (*Person, error) {
		result, err := tx.Run(ctx, "MATCH (p:Person) WHERE p.login = $login RETURN p AS person", map[string]any{
			"login": personLogin,
		})
		if err != nil {
			return nil, err
		}
		record, err := result.Single(ctx)
		if err != nil {
			return nil, err
		}
		key := "person"
		rawPerson, found := record.Get(key)
		if !found {
			return nil, fmt.Errorf("record %q not found", key)
		}
		personNode, ok := rawPerson.(neo4j.Node)
		if !ok {
			return nil, fmt.Errorf("expected result to be a map but was %T", rawPerson)
		}
		name, err := getPropertyValue[string](personNode, "name")
		if err != nil {
			return nil, err
		}
		login, err := getPropertyValue[string](personNode, "login")
		if err != nil {
			return nil, err
		}
		return &Person{
			Name:  name,
			Login: login,
		}, nil
	})
	handleError(err)
	fmt.Printf("Found person %v in the database\n", person)
}

func getPropertyValue[T any](node neo4j.Node, key string) (T, error) {
	zeroValue := *new(T)
	rawValue, found := node.Props[key]
	if !found {
		return zeroValue, fmt.Errorf("could not find property named %q", key)
	}
	value, ok := rawValue.(T)
	if !ok {
		return zeroValue, fmt.Errorf("expected property to be of type %T but was %T", zeroValue, rawValue)
	}
	return value, nil
}

// readPersonLoginFromRequest returns a hardcoded login
// imagine instead an implementation reading the data from an HTTP payload for instance
func readPersonLoginFromRequest() string {
	return "fbiville"
}

func createDriver() (neo4j.DriverWithContext, error) {
	credentials := neo4j.BasicAuth(os.Getenv("USERNAME"), os.Getenv("PASSWORD"), "")
	return neo4j.NewDriverWithContext(os.Getenv("URL"), credentials)
}

type ctxCloser interface {
	Close(context.Context) error
}

func handleClose(ctx context.Context, closer ctxCloser) {
	handleError(closer.Close(ctx))
}

func handleError(err error) {

	if err != nil {

	}
}
Output:

func ExecuteWrite

func ExecuteWrite[T any](ctx context.Context, session SessionWithContext,
	work ManagedTransactionWorkT[T],
	configurers ...func(config *TransactionConfig)) (T, error)

ExecuteWrite executes the given unit of work in a write transaction with retry logic in place, via the provided session.

This is the generic variant of SessionWithContext.ExecuteWrite.

If an error occurs, the zero value of T is returned.

Example
package main

import (
	"context"
	"fmt"
	"github.com/SGNL-ai/neo4j-go-driver/v5/neo4j"
	"os"
)

type Person struct {
	Name  string
	Login string
}

func (p *Person) String() string {
	return fmt.Sprintf("name: %s, login: %s", p.Name, p.Login)
}

func (p *Person) asNodeProps() map[string]any {
	return map[string]any{
		"name":  p.Name,
		"login": p.Login,
	}
}

func main() {
	ctx := context.Background()
	driver, err := createDriver()
	handleError(err)
	defer handleClose(ctx, driver)
	session := driver.NewSession(ctx, neo4j.SessionConfig{})
	defer handleClose(ctx, session)

	person := readPersonFromRequest()

	// with neo4j.ExecuteWrite, `count` is guaranteed to be of the declared type if no error occurs
	// note: if an error occurs, the default value (sometimes called "zero value") of the type is returned
	count, err := neo4j.ExecuteWrite[int64](ctx, session, func(tx neo4j.ManagedTransaction) (int64, error) {
		if err := insertPerson(ctx, tx, person); err != nil {
			return 0, err
		}
		result, err := tx.Run(ctx, "MATCH (p:Person) RETURN count(p) AS count", nil)
		if err != nil {
			return 0, err
		}
		record, err := result.Single(ctx)
		if err != nil {
			return 0, err
		}
		key := "count"
		rawCount, found := record.Get(key)
		if !found {
			return 0, fmt.Errorf("record %q not found", key)
		}
		count, ok := rawCount.(int64)
		if !ok {
			return 0, fmt.Errorf("expected result to be an int64 but was %T", rawCount)
		}
		return count, nil
	})
	handleError(err)
	fmt.Printf("There are %d people in the database\n", count)
}

// readPersonFromRequest returns a hardcoded user
// imagine instead an implementation reading the data from an HTTP payload for instance
func readPersonFromRequest() *Person {
	return &Person{
		Name:  "Jane Doe",
		Login: "@janedoe",
	}
}

func insertPerson(ctx context.Context, tx neo4j.ManagedTransaction, newPerson *Person) error {
	result, err := tx.Run(ctx, "CREATE (p:Person) SET p = $props", map[string]any{
		"props": newPerson.asNodeProps(),
	})
	if err != nil {
		return err
	}
	_, err = result.Consume(ctx)
	return err
}

func createDriver() (neo4j.DriverWithContext, error) {
	credentials := neo4j.BasicAuth(os.Getenv("USERNAME"), os.Getenv("PASSWORD"), "")
	return neo4j.NewDriverWithContext(os.Getenv("URL"), credentials)
}

type ctxCloser interface {
	Close(context.Context) error
}

func handleClose(ctx context.Context, closer ctxCloser) {
	handleError(closer.Close(ctx))
}

func handleError(err error) {

	if err != nil {

	}
}
Output:

func GetProperty

func GetProperty[T PropertyValue](entity Entity, key string) (T, error)

GetProperty returns the value matching the property of the given neo4j.Node or neo4j.Relationship The property type T must adhere to neo4j.PropertyValue If the property does not exist, an error is returned If the property type does not match the type specification, an error is returned

Note: due to the current limited generics support, any property array value other than byte array is typed as []any.

Example
/*
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package main

import (
	"context"
	"fmt"
	"github.com/SGNL-ai/neo4j-go-driver/v5/neo4j"
)

func main() {
	ctx := context.Background()
	driver, err := createDriver()
	handleError(err)
	defer handleClose(ctx, driver)
	session := driver.NewSession(ctx, neo4j.SessionConfig{})
	defer handleClose(ctx, session)

	result, err := session.Run(ctx, "MATCH (p:Person) RETURN p LIMIT 1", nil)
	handleError(err)
	personNode, err := getPersonNode(ctx, result)
	handleError(err)

	// GetProperty extracts the node's or relationship's property by the specified name
	// it also makes sure it matches the specified type parameter
	name, err := neo4j.GetProperty[string](personNode, "name")
	handleError(err)
	login, err := neo4j.GetProperty[string](personNode, "login")
	person := Person{
		Name:  name,
		Login: login,
	}
	fmt.Println(person)
}

func getPersonNode(ctx context.Context, result neo4j.ResultWithContext) (neo4j.Node, error) {
	record, err := result.Single(ctx)
	handleError(err)

	rawPersonNode, found := record.Get("p")
	if !found {
		return neo4j.Node{}, fmt.Errorf("person record not found")
	}
	personNode, ok := rawPersonNode.(neo4j.Node)
	if !ok {
		return neo4j.Node{}, fmt.Errorf("expected person record to be a node, but was %T", rawPersonNode)
	}
	return personNode, nil
}
Output:

func GetRecordValue

func GetRecordValue[T RecordValue](record *Record, key string) (T, bool, error)

GetRecordValue returns the value of the current provided record named by the specified key The value type T must adhere to neo4j.RecordValue If the key specified for the value does not exist, an error is returned If the value is not defined for the provided existing key, the returned boolean is true If the value type does not match the type specification, an error is returned

Take this simple graph made of three nodes: `(:Person {name: "Arya"})`, `(:Person {name: ""})`, `(:Person)` and the query: `MATCH (p:Person) RETURN p.name AS name`. The following code illustrates when an error is returned vs. when the nil flag is set to true:

// the above query has been executed, `result` holds the cursor over the person nodes
for result.Next() {
	record := result.Record()
	name, isNil, err := neo4j.GetRecordValue[string](record, "name")
	// for the person with the non-blank name, name == "Arya", isNil == false, err == nil
	// for the person with the blank name, name == "", isNil == false, err == nil
	// for the node without name, name == "", isNil == true, err == nil

	_, _, err := neo4j.GetRecordValue[string](record, "invalid-key")
	// this results in an error, since "invalid-key" is not part of the query result keys
}
Example
ctx := context.Background()
driver, err := createDriver()
handleError(err)
defer handleClose(ctx, driver)
session := driver.NewSession(ctx, neo4j.SessionConfig{})
defer handleClose(ctx, session)

result, err := session.Run(ctx, "MATCH (p:Person) RETURN p LIMIT 1", nil)
handleError(err)
record, err := result.Single(ctx)
handleError(err)

// GetRecordValue extracts the record value by the specified name
// it also makes sure the value conforms to the specified type parameter
// if a particular value is not present for the current record, isNil will be true
personNode, isNil, err := neo4j.GetRecordValue[neo4j.Node](record, "p")
handleError(err)
if isNil {
	fmt.Println("no person found")
} else {
	fmt.Println(personNode)
}
Output:

func IsConnectivityError

func IsConnectivityError(err error) bool

IsConnectivityError returns true if the provided error is an instance of ConnectivityError.

func IsNeo4jError

func IsNeo4jError(err error) bool

IsNeo4jError returns true if the provided error is an instance of Neo4jError.

func IsRetryable

func IsRetryable(err error) bool

IsRetryable determines whether an operation can be retried based on the error it triggered. This API is meant for use in scenarios where users want to implement their own retry mechanism. A similar logic is used by the driver for transaction functions.

func IsTransactionExecutionLimit

func IsTransactionExecutionLimit(err error) bool

IsTransactionExecutionLimit returns true if the provided error is an instance of TransactionExecutionLimit.

func IsUsageError

func IsUsageError(err error) bool

IsUsageError returns true if the provided error is an instance of UsageError.

func SingleT deprecated

func SingleT[T any](result Result, mapper func(*Record) (T, error)) (T, error)

SingleT maps the single record left to an instance of T with the provided mapper function. It relies on Result.Single and propagate its error, if any.

Deprecated: use SingleTWithContext instead (the entry point of context-aware APIs is NewDriverWithContext)

func SingleTWithContext

func SingleTWithContext[T any](ctx context.Context, result ResultWithContext, mapper func(*Record) (T, error)) (T, error)

SingleTWithContext maps the single record left to an instance of T with the provided mapper function. It relies on ResultWithContext.Single and propagate its error, if any. It accepts a context.Context, which may be canceled or carry a deadline, to control the overall record fetching execution time.

func WithTxMetadata

func WithTxMetadata(metadata map[string]any) func(*TransactionConfig)

WithTxMetadata returns a transaction configuration function that attaches metadata to a transaction.

To attach a metadata to an explicit transaction:

session.BeginTransaction(WithTxMetadata(map[string)any{"work-id": 1}))

To attach a metadata to an auto-commit transaction:

session.Run("RETURN 1", nil, WithTxMetadata(map[string)any{"work-id": 1}))

To attach a metadata to a read transaction function:

session.ExecuteRead(DoWork, WithTxMetadata(map[string)any{"work-id": 1}))

To attach a metadata to a write transaction function:

session.ExecuteWrite(DoWork, WithTxMetadata(map[string)any{"work-id": 1}))

func WithTxTimeout

func WithTxTimeout(timeout time.Duration) func(*TransactionConfig)

WithTxTimeout returns a transaction configuration function that applies a timeout to a transaction.

To apply a transaction timeout to an explicit transaction:

session.BeginTransaction(WithTxTimeout(5*time.Second))

To apply a transaction timeout to an auto-commit transaction:

session.Run("RETURN 1", nil, WithTxTimeout(5*time.Second))

To apply a transaction timeout to a read transaction function:

session.ExecuteRead(DoWork, WithTxTimeout(5*time.Second))

To apply a transaction timeout to a write transaction function:

session.ExecuteWrite(DoWork, WithTxTimeout(5*time.Second))

Types

type AccessMode

type AccessMode int

AccessMode defines modes that routing driver decides to which cluster member a connection should be opened.

const (
	// AccessModeWrite tells the driver to use a connection to 'Leader'
	AccessModeWrite AccessMode = 0
	// AccessModeRead tells the driver to use a connection to one of the 'Follower' or 'Read Replica'.
	AccessModeRead AccessMode = 1
)

type AuthToken

type AuthToken = auth.Token

AuthToken contains credentials to be sent over to the neo4j server.

func BasicAuth

func BasicAuth(username string, password string, realm string) AuthToken

BasicAuth generates a basic authentication token with provided username, password and realm

func BearerAuth

func BearerAuth(token string) AuthToken

BearerAuth generates an authentication token with the provided base-64 value generated by a Single Sign-On provider

func CustomAuth

func CustomAuth(scheme string, username string, password string, realm string, parameters map[string]any) AuthToken

CustomAuth generates a custom authentication token with provided parameters

func KerberosAuth

func KerberosAuth(ticket string) AuthToken

KerberosAuth generates a kerberos authentication token with provided base-64 encoded kerberos ticket

func NoAuth

func NoAuth() AuthToken

NoAuth generates an empty authentication token

type BookmarkManager

type BookmarkManager interface {
	// UpdateBookmarks updates the bookmark tracked by this bookmark manager
	// previousBookmarks are the initial bookmarks of the bookmark holder (like a Session)
	// newBookmarks are the bookmarks that are received after completion of the bookmark holder operation (like the end of a Session)
	UpdateBookmarks(ctx context.Context, previousBookmarks, newBookmarks Bookmarks) error

	// GetBookmarks returns all the bookmarks tracked by this bookmark manager
	// Note: the order of the returned bookmark slice does not need to be deterministic
	GetBookmarks(ctx context.Context) (Bookmarks, error)
}

BookmarkManager centralizes bookmark manager supply and notification

func NewBookmarkManager

func NewBookmarkManager(config BookmarkManagerConfig) BookmarkManager

type BookmarkManagerConfig

type BookmarkManagerConfig struct {
	// Initial bookmarks per database
	InitialBookmarks Bookmarks

	// Supplier providing external bookmarks
	BookmarkSupplier func(context.Context) (Bookmarks, error)

	// Hook called whenever bookmarks get updated
	// The hook is called with the database and the new bookmarks
	// Note: the order of the supplied bookmark slice is not guaranteed
	BookmarkConsumer func(ctx context.Context, bookmarks Bookmarks) error
}

type Bookmarks

type Bookmarks = []string

Bookmarks is a holder for server-side bookmarks which are used for causally-chained sessions. See also CombineBookmarks. Note: this will be changed from being a type alias to being a struct in 6.0. Please use BookmarksFromRawValues for construction from raw values and BookmarksToRawValues for accessing the raw values.

func BookmarksFromRawValues

func BookmarksFromRawValues(values ...string) Bookmarks

BookmarksFromRawValues creates Bookmarks from raw server-side bookmarks. You should not need to use this method unless you want to de-serialize bookmarks. See Session.LastBookmarks and CombineBookmarks for alternatives.

func CombineBookmarks

func CombineBookmarks(bookmarks ...Bookmarks) Bookmarks

CombineBookmarks is a helper method to combine []Bookmarks into a single Bookmarks instance. Let s1, s2, s3 be Session interfaces. You can easily causally chain the sessions like so: ```go

s4 := driver.NewSession(neo4j.SessionConfig{
	Bookmarks: neo4j.CombineBookmarks(s1.LastBookmarks(), s2.LastBookmarks(), s3.LastBookmarks()),
})

``` The server will then make sure to execute all transactions in s4 after any that were already executed in s1, s2, or s3 at the time of calling LastBookmarks.

type Config deprecated

type Config = config.Config

Deprecated: please use config.Config directly. This alias will be removed in 6.0.

Example (DisableNoCategories)
ctx := context.Background()
driver, err := NewDriverWithContext(getUrl(), getAuth(), func(config *Config) {
	// makes the server return all notification categories
	config.NotificationsDisabledCategories = notifications.DisableNoCategories()
})
handleError(err)
defer handleClose(ctx, driver)

result, err := ExecuteQuery(ctx, driver, someDeprecatedQuery(), nil, EagerResultTransformer)
handleError(err)

for _, notification := range result.Summary.Notifications() {
	fmt.Println("description:", notification.Description())
	fmt.Println("category: ", notification.RawCategory())
	fmt.Println("severity: ", notification.RawSeverityLevel())
}
Output:

Example (DisableSomeCategories)
ctx := context.Background()
driver, err := NewDriverWithContext(getUrl(), getAuth(), func(config *Config) {
	// makes the server return all notification categories but deprecations
	config.NotificationsDisabledCategories = notifications.DisableCategories(notifications.Deprecation)
})
handleError(err)
defer handleClose(ctx, driver)

result, err := ExecuteQuery(ctx, driver, someDeprecatedQuery(), nil, EagerResultTransformer)
handleError(err)

// will not see the deprecation notification
for _, notification := range result.Summary.Notifications() {
	fmt.Println("description:", notification.Description())
	fmt.Println("category: ", notification.RawCategory())
	fmt.Println("severity: ", notification.RawSeverityLevel())
}
Output:

Example (MinimumSeverityLevel)
ctx := context.Background()
driver, err := NewDriverWithContext(getUrl(), getAuth(), func(config *Config) {
	// makes the server return only notifications with severity level warning or higher
	config.NotificationsMinSeverity = notifications.WarningLevel
})
handleError(err)
defer handleClose(ctx, driver)

result, err := ExecuteQuery(ctx, driver, someQueryWithInformationNotification(), nil, EagerResultTransformer)
handleError(err)

// will only see notifications with severity level warning or higher
for _, notification := range result.Summary.Notifications() {
	fmt.Println("description:", notification.Description())
	fmt.Println("category: ", notification.RawCategory())
	fmt.Println("severity: ", notification.RawSeverityLevel())
}
Output:

type ConnectivityError

type ConnectivityError = errorutil.ConnectivityError

type Counters

type Counters interface {
	// Whether there were any updates at all, eg. any of the counters are greater than 0.
	ContainsUpdates() bool
	// The number of nodes created.
	NodesCreated() int
	// The number of nodes deleted.
	NodesDeleted() int
	// The number of relationships created.
	RelationshipsCreated() int
	// The number of relationships deleted.
	RelationshipsDeleted() int
	PropertiesSet() int
	// The number of labels added to nodes.
	LabelsAdded() int
	// The number of labels removed from nodes.
	LabelsRemoved() int
	// The number of indexes added to the schema.
	IndexesAdded() int
	// The number of indexes removed from the schema.
	IndexesRemoved() int
	// The number of constraints added to the schema.
	ConstraintsAdded() int
	// The number of constraints removed from the schema.
	ConstraintsRemoved() int
	// The number of system updates
	SystemUpdates() int
	// ContainsSystemUpdates indicates whether the query contains system updates
	ContainsSystemUpdates() bool
}

Counters contains statistics about the changes made to the database made as part of the statement execution.

type DatabaseInfo

type DatabaseInfo interface {
	Name() string
}

DatabaseInfo contains basic information of the database the query result has been obtained from.

type Date

type Date = dbtype.Date

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

func DateOf

func DateOf(t time.Time) Date

DateOf creates a neo4j.Date from time.Time. Hour, minute, second and nanoseconds are set to zero and location is set to UTC.

Conversion can also be done by casting a time.Time to neo4j.Date but beware that time components and location will be left as is but ignored when used as query parameter.

type Driver

type Driver interface {
	// Target returns the url this driver is bootstrapped
	Target() url.URL
	// NewSession creates a new session based on the specified session configuration.
	NewSession(config SessionConfig) Session
	// VerifyConnectivity checks that the driver can connect to a remote server or cluster by
	// establishing a network connection with the remote. Returns nil if succesful
	// or error describing the problem.
	VerifyConnectivity() error
	// Close the driver and all underlying connections
	Close() error
	// IsEncrypted determines whether the driver communication with the server
	// is encrypted. This is a static check. The function can also be called on
	// a closed Driver.
	IsEncrypted() bool
}

Driver represents a pool(s) of connections to a neo4j server or cluster. It's safe for concurrent use. Deprecated: please use DriverWithContext instead. This interface will be removed in 6.0.

func NewDriver deprecated

func NewDriver(target string, auth AuthToken, configurers ...func(*Config)) (Driver, error)

NewDriver is the entry point to the neo4j driver to create an instance of a Driver. It is the first function to be called in order to establish a connection to a neo4j database. It requires a Bolt URI and an authentication token as parameters and can also take optional configuration function(s) as variadic parameters.

In order to connect to a single instance database, you need to pass a URI with scheme 'bolt', 'bolt+s' or 'bolt+ssc'.

driver, err = NewDriver("bolt://db.server:7687", BasicAuth(username, password))

In order to connect to a causal cluster database, you need to pass a URI with scheme 'neo4j', 'neo4j+s' or 'neo4j+ssc' and its host part set to be one of the core cluster members.

driver, err = NewDriver("neo4j://core.db.server:7687", BasicAuth(username, password))

You can override default configuration options by providing a configuration function(s)

driver, err = NewDriver(uri, BasicAuth(username, password), function (config *Config) {
	config.MaxConnectionPoolSize = 10
})

Deprecated: please use NewDriverWithContext instead. This function will be removed in 6.0.

type DriverWithContext

type DriverWithContext interface {
	// ExecuteQueryBookmarkManager returns the bookmark manager instance used by ExecuteQuery by default.
	//
	// This is useful when ExecuteQuery is called without custom bookmark managers and the lower-level
	// neo4j.SessionWithContext APIs are called as well.
	// In that case, the recommended approach is as follows:
	// 	results, err := driver.ExecuteQuery(ctx, query, params)
	// 	// [...] do something with results and error
	//	bookmarkManager := driver.ExecuteQueryBookmarkManager()
	// 	// maintain consistency with sessions as well
	//	session := driver.NewSession(ctx, neo4j.SessionConfig {BookmarkManager: bookmarkManager})
	//	// [...] run something within the session
	ExecuteQueryBookmarkManager() BookmarkManager
	// Target returns the url this driver is bootstrapped
	Target() url.URL
	// NewSession creates a new session based on the specified session configuration.
	NewSession(ctx context.Context, config SessionConfig) SessionWithContext
	// VerifyConnectivity checks that the driver can connect to a remote server or cluster by
	// establishing a network connection with the remote. Returns nil if successful
	// or error describing the problem.
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	VerifyConnectivity(ctx context.Context) error
	// VerifyAuthentication verifies that the authentication information is valid.
	//
	// It's much like `DriverWithContext.VerifyConnectivity`, but for checking authentication.
	//
	// Passing `nil` as `auth` will use the authentication information that was used to create the driver.
	//
	// Tries to establish a working read connection to the remote server or a member of a cluster and exchange some data.
	// In a cluster, there is no guarantee about which server will be contacted.
	// If the data exchange is successful, the authentication information is valid no error is returned.
	// Otherwise, the error will be matched against a list of known authentication errors.
	// If the error is on that list, an `neo4j.InvalidAuthenticationError` is returned.
	// Otherwise, the original error is returned.
	//
	// VerifyAuthentication is part of the re-authentication preview feature
	// (see README on what it means in terms of support and compatibility guarantees)
	VerifyAuthentication(ctx context.Context, auth *AuthToken) error
	// Close the driver and all underlying connections
	Close(ctx context.Context) error
	// IsEncrypted determines whether the driver communication with the server
	// is encrypted. This is a static check. The function can also be called on
	// a closed Driver.
	IsEncrypted() bool
	// GetServerInfo attempts to obtain server information from the target Neo4j
	// deployment
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	GetServerInfo(ctx context.Context) (ServerInfo, error)
}

DriverWithContext represents a pool of connections to a neo4j server or cluster. It's safe for concurrent use.

Example (VerifyAuthentication)
driver, err := NewDriverWithContext(getUrl(), NoAuth())
handleError(err)
someToken := BasicAuth("neo4j", "password", "")
// verify `someToken` is valid
err = driver.VerifyAuthentication(context.Background(), &someToken)
if err == nil {
	return // authentication is valid
}
var invalidAuth *InvalidAuthenticationError
if errors.As(err, &invalidAuth) {
	// handle the issue
	panic("authentication is invalid")
}
// some other error occurred
handleError(err)
Output:

Example (VerifyAuthenticationDriverLevel)
driver, err := NewDriverWithContext(getUrl(), NoAuth())
handleError(err)
// verify `NoAuth()` configured at driver creation is valid
err = driver.VerifyAuthentication(context.Background(), nil)
if err == nil {
	return // authentication is valid
}
var invalidAuth *InvalidAuthenticationError
if errors.As(err, &invalidAuth) {
	// handle the issue
	panic("authentication is invalid")
}
// some other error occurred
handleError(err)
Output:

func NewDriverWithContext

func NewDriverWithContext(target string, auth auth.TokenManager, configurers ...func(*Config)) (DriverWithContext, error)

NewDriverWithContext is the entry point to the neo4j driver to create an instance of a Driver. It is the first function to be called in order to establish a connection to a neo4j database. It requires a Bolt URI and authentication as parameters and can also take optional configuration function(s) as variadic parameters.

No connectivity happens when NewDriverWithContext is called. Call DriverWithContext.VerifyConnectivity once the driver is created if you want to eagerly check that the provided URI and credentials are correct.

In order to connect to a single instance database, you need to pass a URI with scheme 'bolt', 'bolt+s' or 'bolt+ssc'.

driver, err = NewDriverWithContext("bolt://db.server:7687", BasicAuth(username, password))

In order to connect to a causal cluster database, you need to pass a URI with scheme 'neo4j', 'neo4j+s' or 'neo4j+ssc' and its host part set to be one of the core cluster members.

driver, err = NewDriverWithContext("neo4j://core.db.server:7687", BasicAuth(username, password))

You can override default configuration options by providing a configuration function(s)

driver, err = NewDriverWithContext(uri, BasicAuth(username, password), function (config *Config) {
	config.MaxConnectionPoolSize = 10
})

The authentication can be nil, in which case the driver will not authenticate with the server. Else, an implementation of `auth.TokenManager` is required. The `neo4j` package provides default implementations of `auth.TokenManager` for common authentication schemes:

  • `neo4j.NoAuth` (equivalent to `nil`)
  • `neo4j.BasicAuth`
  • `neo4j.KerberosAuth`
  • `neo4j.BearerAuth`
  • `neo4j.CustomAuth`

`TokenManager` is part of the re-authentication preview feature (see README on what it means in terms of support and compatibility guarantees). The pre-defined auth mechanisms listed above however are guaranteed to be supported as `auth` argument to this function.

type Duration

type Duration = dbtype.Duration

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

func DurationOf

func DurationOf(months, days, seconds int64, nanos int) Duration

DurationOf creates neo4j.Duration from specified time parts.

type EagerResult

type EagerResult struct {
	Keys    []string
	Records []*Record
	Summary ResultSummary
}

EagerResult holds the result and result metadata of the query executed via DriverWithContext.ExecuteQuery

type Entity

type Entity = dbtype.Entity

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

type ExecuteQueryConfiguration

type ExecuteQueryConfiguration struct {
	Routing          RoutingControl
	ImpersonatedUser string
	Database         string
	BookmarkManager  BookmarkManager
	BoltLogger       log.BoltLogger
}

ExecuteQueryConfiguration holds all the possible configuration settings for DriverWithContext.ExecuteQuery

type ExecuteQueryConfigurationOption

type ExecuteQueryConfigurationOption func(*ExecuteQueryConfiguration)

ExecuteQueryConfigurationOption is a callback that configures the execution of DriverWithContext.ExecuteQuery

func ExecuteQueryWithBoltLogger

func ExecuteQueryWithBoltLogger(boltLogger log.BoltLogger) ExecuteQueryConfigurationOption

ExecuteQueryWithBoltLogger configures DriverWithContext.ExecuteQuery to log Bolt messages with the provided BoltLogger

func ExecuteQueryWithBookmarkManager

func ExecuteQueryWithBookmarkManager(bookmarkManager BookmarkManager) ExecuteQueryConfigurationOption

ExecuteQueryWithBookmarkManager configures DriverWithContext.ExecuteQuery to rely on the specified BookmarkManager

func ExecuteQueryWithDatabase

func ExecuteQueryWithDatabase(db string) ExecuteQueryConfigurationOption

ExecuteQueryWithDatabase configures DriverWithContext.ExecuteQuery to target the specified database

func ExecuteQueryWithImpersonatedUser

func ExecuteQueryWithImpersonatedUser(user string) ExecuteQueryConfigurationOption

ExecuteQueryWithImpersonatedUser configures DriverWithContext.ExecuteQuery to impersonate the specified user

func ExecuteQueryWithReadersRouting

func ExecuteQueryWithReadersRouting() ExecuteQueryConfigurationOption

ExecuteQueryWithReadersRouting configures DriverWithContext.ExecuteQuery to route to reader members of the cluster

func ExecuteQueryWithWritersRouting

func ExecuteQueryWithWritersRouting() ExecuteQueryConfigurationOption

ExecuteQueryWithWritersRouting configures DriverWithContext.ExecuteQuery to route to writer members of the cluster

func ExecuteQueryWithoutBookmarkManager

func ExecuteQueryWithoutBookmarkManager() ExecuteQueryConfigurationOption

ExecuteQueryWithoutBookmarkManager configures DriverWithContext.ExecuteQuery to not rely on any BookmarkManager

type ExplicitTransaction

type ExplicitTransaction interface {
	// Run executes a statement on this transaction and returns a result
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	Run(ctx context.Context, cypher string, params map[string]any) (ResultWithContext, error)
	// Commit commits the transaction
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	Commit(ctx context.Context) error
	// Rollback rolls back the transaction
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	Rollback(ctx context.Context) error
	// Close rolls back the actual transaction if it's not already committed/rolled back
	// and closes all resources associated with this transaction
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	Close(ctx context.Context) error
	// contains filtered or unexported methods
}

ExplicitTransaction represents a transaction in the Neo4j database

type InputPosition

type InputPosition interface {
	// Offset returns the character offset referred to by this position; offset numbers start at 0.
	Offset() int
	// Line returns the line number referred to by this position; line numbers start at 1.
	Line() int
	// Column returns the column number referred to by this position; column numbers start at 1.
	Column() int
}

InputPosition contains information about a specific position in a statement

type InvalidAuthenticationError

type InvalidAuthenticationError struct {
	// contains filtered or unexported fields
}

func (*InvalidAuthenticationError) Error

func (*InvalidAuthenticationError) Unwrap

func (i *InvalidAuthenticationError) Unwrap() error

type InvalidValue

type InvalidValue = dbtype.InvalidValue

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

type LocalDateTime

type LocalDateTime = dbtype.LocalDateTime

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

func LocalDateTimeOf

func LocalDateTimeOf(t time.Time) LocalDateTime

LocalDateTimeOf creates a neo4j.Local from time.Time.

Conversion can also be done by casting a time.Time to neo4j.LocalTime but beware that location will be left as is but interpreted as local when used as query parameter.

type LocalTime

type LocalTime = dbtype.LocalTime

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

func LocalTimeOf

func LocalTimeOf(t time.Time) LocalTime

LocalTimeOf creates a neo4j.LocalTime from time.Time. Year, month and day are set to zero and location is set to local.

Conversion can also be done by casting a time.Time to neo4j.LocalTime but beware that date components and location will be left as is but ignored when used as query parameter.

type LogLevel

type LogLevel int

LogLevel is the type that default logging implementations use for available log levels

type ManagedTransaction

type ManagedTransaction interface {
	// Run executes a statement on this transaction and returns a result
	Run(ctx context.Context, cypher string, params map[string]any) (ResultWithContext, error)
	// contains filtered or unexported methods
}

ManagedTransaction represents a transaction managed by the driver and operated on by the user, via transaction functions

type ManagedTransactionWork

type ManagedTransactionWork func(tx ManagedTransaction) (any, error)

ManagedTransactionWork represents a unit of work that will be executed against the provided transaction

type ManagedTransactionWorkT

type ManagedTransactionWorkT[T any] func(tx ManagedTransaction) (T, error)

type Neo4jError

type Neo4jError = db.Neo4jError

Neo4jError represents errors originating from Neo4j service. Alias for convenience. This error is defined in db package and used internally.

type Node

type Node = dbtype.Node

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

type Notification

type Notification interface {
	// Code returns a notification code for the discovered issue of this notification.
	Code() string
	// Title returns a short summary of this notification.
	Title() string
	// Description returns a longer description of this notification.
	Description() string
	// Position returns the position in the statement where this notification points to.
	// Not all notifications have a unique position to point to and in that case the position would be set to nil.
	Position() InputPosition
	// Severity returns the severity level of this notification.
	// Deprecated: Severity will be removed in 6.0.
	// Please rely on SeverityLevel (or RawSeverityLevel) instead.
	Severity() string
	// RawSeverityLevel returns the unmapped severity level of this notification.
	// This is useful when the driver cannot interpret the severity level returned by the server
	// In that case, SeverityLevel returns UnknownSeverity while RawSeverityLevel returns the raw string
	RawSeverityLevel() string
	// RawCategory returns the unmapped category of this notification.
	// This is useful when the driver cannot interpret the category returned by the server
	// In that case, Category returns UnknownCategory while RawCategory returns the raw string
	RawCategory() string
	// SeverityLevel returns the mapped security level of this notification.
	// If the severity level is not a known value, SeverityLevel returns UnknownSeverity
	// Call RawSeverityLevel to get access to the raw string value
	SeverityLevel() NotificationSeverity
	// Category returns the mapped category of this notification.
	// If the category is not a known value, Category returns UnknownCategory
	// Call RawCategory to get access to the raw string value
	Category() NotificationCategory
}

Notification represents notifications generated when executing a statement. A notification can be visualized in a client pinpointing problems or other information about the statement. Contrary to failures or errors, notifications do not affect the execution of the statement.

type NotificationCategory

type NotificationCategory string
const (
	Hint            NotificationCategory = "HINT"
	Unrecognized    NotificationCategory = "UNRECOGNIZED"
	Unsupported     NotificationCategory = "UNSUPPORTED"
	Performance     NotificationCategory = "PERFORMANCE"
	Deprecation     NotificationCategory = "DEPRECATION"
	Generic         NotificationCategory = "GENERIC"
	UnknownCategory NotificationCategory = "UNKNOWN"
)

type NotificationSeverity

type NotificationSeverity string
const (
	Warning         NotificationSeverity = "WARNING"
	Information     NotificationSeverity = "INFORMATION"
	UnknownSeverity NotificationSeverity = "UNKNOWN"
)

type OffsetTime

type OffsetTime = dbtype.Time

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

func OffsetTimeOf

func OffsetTimeOf(t time.Time) OffsetTime

OffsetTimeOf creates a neo4j.OffsetTime from time.Time. Year, month and day are set to zero and location is set to "Offset" using zone offset from time.Time.

Conversion can also be done by casting a time.Time to neo4j.OffsetTime but beware that date components and location will be left as is but ignored when used as query parameter. Since location will contain the original value, the value "offset" will not be used by the driver but the actual name of the location in time.Time and that offset.

type Path

type Path = dbtype.Path

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

type Plan

type Plan interface {
	// Operator returns the operation this plan is performing.
	Operator() string
	// Arguments returns the arguments for the operator used.
	// Many operators have arguments defining their specific behavior. This map contains those arguments.
	Arguments() map[string]any
	// Identifiers returns a list of identifiers used by this plan. Identifiers used by this part of the plan.
	// These can be both identifiers introduced by you, or automatically generated.
	Identifiers() []string
	// Children returns zero or more child plans. A plan is a tree, where each child is another plan.
	// The children are where this part of the plan gets its input records - unless this is an operator that
	// introduces new records on its own.
	Children() []Plan
}

Plan describes the actual plan that the database planner produced and used (or will use) to execute your statement. This can be extremely helpful in understanding what a statement is doing, and how to optimize it. For more details, see the Neo4j Manual. The plan for the statement is a tree of plans - each sub-tree containing zero or more child plans. The statement starts with the root plan. Each sub-plan is of a specific operator, which describes what that part of the plan does - for instance, perform an index lookup or filter results. The Neo4j Manual contains a reference of the available operator types, and these may differ across Neo4j versions.

type Point2D

type Point2D = dbtype.Point2D

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

type Point3D

type Point3D = dbtype.Point3D

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

type ProfiledPlan

type ProfiledPlan interface {
	// Operator returns the operation this plan is performing.
	Operator() string
	// Arguments returns the arguments for the operator used.
	// Many operators have arguments defining their specific behavior. This map contains those arguments.
	Arguments() map[string]any
	// Identifiers returns a list of identifiers used by this plan. Identifiers used by this part of the plan.
	// These can be both identifiers introduced by you, or automatically generated.
	Identifiers() []string
	// DbHits returns the number of times this part of the plan touched the underlying data stores/
	DbHits() int64
	// Records returns the number of records this part of the plan produced.
	Records() int64
	// Children returns zero or more child plans. A plan is a tree, where each child is another plan.
	// The children are where this part of the plan gets its input records - unless this is an operator that
	// introduces new records on its own.
	Children() []ProfiledPlan
	PageCacheMisses() int64
	PageCacheHits() int64
	PageCacheHitRatio() float64
	Time() int64
}

ProfiledPlan is the same as a regular Plan - except this plan has been executed, meaning it also contains detailed information about how much work each step of the plan incurred on the database.

type PropertyValue

type PropertyValue interface {
	bool | int64 | float64 | string |
		Point2D | Point3D |
		Date | LocalTime | LocalDateTime | Time | Duration |
		[]byte | []any
}

type Query

type Query interface {
	// Text returns the statement's text.
	Text() string
	// Parameters returns the statement's parameters.
	Parameters() map[string]any
}

type Record

type Record = db.Record

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

func AsRecord

func AsRecord(from any, err error) (*Record, error)

AsRecord passes any existing error or casts from to a record. Use in combination with Single and transactional functions:

record, err := neo4j.AsRecord(session.ExecuteRead(func (tx neo4j.Transaction) {
    return neo4j.Single(tx.Run(...))
}))

func AsRecords

func AsRecords(from any, err error) ([]*Record, error)

AsRecords passes any existing error or casts from to a slice of records. Use in combination with Collect and transactional functions:

records, err := neo4j.AsRecords(session.ExecuteRead(func (tx neo4j.Transaction) {
    return neo4j.Collect(tx.Run(...))
}))

func Collect deprecated

func Collect(result Result, err error) ([]*Record, error)

Collect aggregates the records into a slice. It relies on Result.Collect and propagate its error, if any.

records, err := neo4j.Collect(session.Run(...))

Deprecated: use CollectWithContext instead (the entry point of context-aware APIs is NewDriverWithContext)

func CollectWithContext

func CollectWithContext(ctx context.Context, result ResultWithContext, err error) ([]*Record, error)

CollectWithContext aggregates the records into a slice. It relies on ResultWithContext.Collect and propagate its error, if any.

result, err := session.Run(...)
records, err := neo4j.CollectWithContext(ctx, result, err)

It accepts a context.Context, which may be canceled or carry a deadline, to control the overall record fetching execution time.

func Single

func Single(result Result, err error) (*Record, error)

Single returns one and only one record from the result stream. Any error passed in or reported while navigating the result stream is returned without any conversion. If the result stream contains zero or more than one records error is returned.

record, err := neo4j.Single(session.Run(...))

type RecordValue

type RecordValue interface {
	bool | int64 | float64 | string |
		Point2D | Point3D |
		Date | LocalTime | LocalDateTime | Time | Duration |
		[]byte | []any | map[string]any |
		Node | Relationship | Path
}

type Relationship

type Relationship = dbtype.Relationship

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

type Result deprecated

type Result interface {
	// Keys returns the keys available on the result set.
	Keys() ([]string, error)
	// Next returns true only if there is a record to be processed.
	Next() bool
	// NextRecord returns true if there is a record to be processed, record parameter is set
	// to point to current record.
	NextRecord(record **Record) bool
	// PeekRecord returns true if there is a record after the current one to be processed without advancing the record
	// stream, record parameter is set to point to that record if present.
	PeekRecord(record **Record) bool
	// Err returns the latest error that caused this Next to return false.
	Err() error
	// Record returns the current record.
	Record() *Record
	// Collect fetches all remaining records and returns them.
	Collect() ([]*Record, error)
	// Single returns one and only one record from the stream.
	// If the result stream contains zero or more than one records, error is returned.
	Single() (*Record, error)
	// Consume discards all remaining records and returns the summary information
	// about the statement execution.
	Consume() (ResultSummary, error)
}

Deprecated: use ResultWithContext instead. ResultWithContext is created via the context-aware SessionWithContext type.

type ResultSummary

type ResultSummary interface {
	// Server returns basic information about the server where the statement is carried out.
	Server() ServerInfo
	// Query returns the query that has been executed.
	Query() Query
	// StatementType returns type of statement that has been executed.
	StatementType() StatementType
	// Counters returns statistics counts for the statement.
	Counters() Counters
	// Plan returns statement plan for the executed statement if available, otherwise null.
	Plan() Plan
	// Profile returns profiled statement plan for the executed statement if available, otherwise null.
	Profile() ProfiledPlan
	// Notifications returns a slice of notifications produced while executing the statement.
	// The list will be empty if no notifications produced while executing the statement.
	Notifications() []Notification
	// ResultAvailableAfter returns the time it took for the server to make the result available for consumption.
	// Since 5.0, this returns a negative duration if the server has not sent the corresponding statistic.
	ResultAvailableAfter() time.Duration
	// ResultConsumedAfter returns the time it took the server to consume the result.
	// Since 5.0, this returns a negative duration if the server has not sent the corresponding statistic.
	ResultConsumedAfter() time.Duration
	// Database returns information about the database where the result is obtained from
	// Returns nil for Neo4j versions prior to v4.
	// Returns the default "neo4j" database for Community Edition servers.
	Database() DatabaseInfo
}

type ResultTransformer

type ResultTransformer[T any] interface {
	// Accept is called whenever a new record is fetched from the server
	// Implementers are free to accumulate or discard the specified record
	Accept(*Record) error

	// Complete is called when the record fetching is over and no error occurred.
	// In particular, it is important to note that Accept may be called several times before an error occurs.
	// In that case, Complete will not be called.
	Complete(keys []string, summary ResultSummary) (T, error)
}

ResultTransformer is a record accumulator that produces an instance of T when the processing of records is over.

func EagerResultTransformer

func EagerResultTransformer() ResultTransformer[*EagerResult]

type ResultWithContext

type ResultWithContext interface {
	// Keys returns the keys available on the result set.
	Keys() ([]string, error)
	// NextRecord returns true if there is a record to be processed, record parameter is set
	// to point to current record.
	NextRecord(ctx context.Context, record **Record) bool
	// Next returns true only if there is a record to be processed.
	Next(ctx context.Context) bool
	// PeekRecord returns true if there is a record after the current one to be processed without advancing the record
	// stream, record parameter is set to point to that record if present.
	PeekRecord(ctx context.Context, record **Record) bool
	// Peek returns true only if there is a record after the current one to be processed without advancing the record
	// stream
	Peek(ctx context.Context) bool
	// Err returns the latest error that caused this Next to return false.
	Err() error
	// Record returns the current record.
	Record() *Record
	// Collect fetches all remaining records and returns them.
	Collect(ctx context.Context) ([]*Record, error)
	// Single returns the only remaining record from the stream.
	// If none or more than one record is left, an error is returned.
	// The result is fully consumed after this call and its summary is immediately available when calling Consume.
	Single(ctx context.Context) (*Record, error)
	// Consume discards all remaining records and returns the summary information
	// about the statement execution.
	Consume(ctx context.Context) (ResultSummary, error)
	// IsOpen determines whether this result cursor is available
	IsOpen() bool
	// contains filtered or unexported methods
}

type RoutingControl

type RoutingControl int

RoutingControl specifies how the query executed by DriverWithContext.ExecuteQuery is to be routed

const (
	// Write routes the query to execute to a writer member of the cluster
	Write RoutingControl = iota
	// Read routes the query to execute to a writer member of the cluster
	Read
)

type ServerAddress deprecated

type ServerAddress = config.ServerAddress

Deprecated: please use config.ServerAddress directly. This alias will be removed in 6.0.

func NewServerAddress

func NewServerAddress(hostname string, port string) ServerAddress

NewServerAddress generates a ServerAddress with provided hostname and port information.

type ServerAddressResolver deprecated

type ServerAddressResolver = config.ServerAddressResolver

Deprecated: please use config.ServerAddressResolver directly. This alias will be removed in 6.0.

type ServerInfo

type ServerInfo interface {
	// Address returns the address of the server.
	Address() string
	Agent() string
	ProtocolVersion() db.ProtocolVersion
}

ServerInfo contains basic information of the server.

type Session

type Session interface {
	// LastBookmarks returns the bookmark received following the last successfully completed transaction.
	// If no bookmark was received or if this transaction was rolled back, the initial set of bookmarks will be
	// returned.
	LastBookmarks() Bookmarks
	// LastBookmark returns the bookmark received following the last successfully completed transaction.
	// If no bookmark was received or if this transaction was rolled back, the bookmark value will not be changed.
	// Deprecated: since version 5.0. Will be removed in 6.0. Use LastBookmarks instead.
	// Warning: this method can lead to unexpected behaviour if the session has not yet successfully completed a
	// transaction.
	LastBookmark() string
	// BeginTransaction starts a new explicit transaction on this session
	BeginTransaction(configurers ...func(*TransactionConfig)) (Transaction, error)
	// ReadTransaction executes the given unit of work in a AccessModeRead transaction with
	// retry logic in place
	ReadTransaction(work TransactionWork, configurers ...func(*TransactionConfig)) (any, error)
	// WriteTransaction executes the given unit of work in a AccessModeWrite transaction with
	// retry logic in place
	WriteTransaction(work TransactionWork, configurers ...func(*TransactionConfig)) (any, error)
	// Run executes an auto-commit statement and returns a result
	Run(cypher string, params map[string]any, configurers ...func(*TransactionConfig)) (Result, error)
	// Close closes any open resources and marks this session as unusable
	Close() error
}

Session represents a logical connection (which is not tied to a physical connection) to the server Deprecated: use SessionWithContext instead. SessionWithContext is created via the context-aware driver returned by NewDriverWithContext. Session will be removed in 6.0.

type SessionConfig

type SessionConfig struct {
	// AccessMode used when using Session.Run and explicit transactions. Used to route query
	// to read or write servers when running in a cluster. Session.ReadTransaction and Session.WriteTransaction
	// does not rely on this mode.
	AccessMode AccessMode
	// Bookmarks are the initial bookmarks used to ensure that the executing server is at least up
	// to date to the point represented by the latest of the provided bookmarks. After running commands
	// on the session the bookmark can be retrieved with Session.LastBookmark. All commands executing
	// within the same session will automatically use the bookmark from the previous command in the
	// session.
	Bookmarks Bookmarks
	// DatabaseName sets the target database name for the queries executed within the session created with this
	// configuration.
	// Usage of Cypher clauses like USE is not a replacement for this option.
	// Drive​r sends Cypher to the server for processing.
	// This option has no explicit value by default, but it is recommended to set one if the target database is known
	// in advance. This has the benefit of ensuring a consistent target database name throughout the session in a
	// straightforward way and potentially simplifies driver logic as well as reduces network communication resulting
	// in better performance.
	// When no explicit name is set, the driver behavior depends on the connection URI scheme supplied to the driver on
	// instantiation and Bolt protocol version.
	//
	// Specifically, the following applies:
	//
	// - for bolt schemes
	//		queries are dispatched to the server for execution without explicit database name supplied,
	// 		meaning that the target database name for query execution is determined by the server.
	//		It is important to note that the target database may change (even within the same session), for instance if the
	//		user's home database is changed on the server.
	//
	// - for neo4j schemes
	//		providing that Bolt protocol version 4.4, which was introduced with Neo4j server 4.4, or above
	//		is available, the driver fetches the user's home database name from the server on first query execution
	//		within the session and uses the fetched database name explicitly for all queries executed within the session.
	//		This ensures that the database name remains consistent within the given session. For instance, if the user's
	//		home database name is 'movies' and the server supplies it to the driver upon database name fetching for the
	//		session, all queries within that session are executed with the explicit database name 'movies' supplied.
	//		Any change to the user’s home database is reflected only in sessions created after such change takes effect.
	//		This behavior requires additional network communication.
	//		In clustered environments, it is strongly recommended to avoid a single point of failure.
	//		For instance, by ensuring that the connection URI resolves to multiple endpoints.
	//		For older Bolt protocol versions, the behavior is the same as described for the bolt schemes above.
	DatabaseName string
	// FetchSize defines how many records to pull from server in each batch.
	// From Bolt protocol v4 (Neo4j 4+) records can be fetched in batches as compared to fetching
	// all in previous versions.
	//
	// If FetchSize is set to FetchDefault, the driver decides the appropriate size. If set to a positive value
	// that size is used if the underlying protocol supports it otherwise it is ignored.
	//
	// To turn off fetching in batches and always fetch everything, set FetchSize to FetchAll.
	// If a single large result is to be retrieved this is the most performant setting.
	FetchSize int
	// Logging target the session will send its Bolt message traces
	//
	// Possible to use custom logger (implement log.BoltLogger interface) or
	// use neo4j.ConsoleBoltLogger.
	BoltLogger log.BoltLogger
	// ImpersonatedUser sets the Neo4j user that the session will be acting as.
	// If not set, the user configured for the driver will be used.
	//
	// If user impersonation is used, the default database for that impersonated
	// user will be used unless DatabaseName is set.
	//
	// In the former case, when routing is enabled, using impersonation
	// without DatabaseName will cause the driver to query the
	// cluster for the name of the default database of the impersonated user.
	// This is done at the beginning of the session so that queries are routed
	// to the correct cluster member (different databases may have different
	// leaders).
	ImpersonatedUser string
	// BookmarkManager defines a central point to externally supply bookmarks
	// and be notified of bookmark updates per database
	// Since 5.0
	// default: nil (no-op)
	BookmarkManager BookmarkManager
	// NotificationsMinSeverity defines the minimum severity level of notifications the server should send.
	// By default, the driver's settings are used.
	// Else, this option overrides the driver's settings.
	NotificationsMinSeverity notifications.NotificationMinimumSeverityLevel
	// NotificationsDisabledCategories defines the categories of notifications the server should not send.
	// By default, the driver's settings are used.
	// Else, this option overrides the driver's settings.
	NotificationsDisabledCategories notifications.NotificationDisabledCategories
	// Auth is used to overwrite the authentication information for the session.
	// This requires the server to support re-authentication on the protocol level.
	// `nil` will make the driver use the authentication information from the driver configuration.
	// The `neo4j` package provides factory functions for common authentication schemes:
	//   - `neo4j.NoAuth`
	//   - `neo4j.BasicAuth`
	//   - `neo4j.KerberosAuth`
	//   - `neo4j.BearerAuth`
	//   - `neo4j.CustomAuth`
	//
	// Session auth is part of the re-authentication preview feature
	// (see README on what it means in terms of support and compatibility guarantees).
	Auth *AuthToken
	// contains filtered or unexported fields
}

SessionConfig is used to configure a new session, its zero value uses safe defaults.

Example (DisableNoCategories)
ctx := context.Background()
driver, err := NewDriverWithContext(getUrl(), getAuth())
handleError(err)
defer handleClose(ctx, driver)

session := driver.NewSession(ctx, SessionConfig{
	// makes the server return all notification categories
	// this overrides the driver level configuration of the same name
	NotificationsDisabledCategories: notifications.DisableNoCategories(),
})

result, err := session.Run(ctx, someDeprecatedQuery(), nil)
handleError(err)

summary, err := result.Consume(ctx)
handleError(err)

for _, notification := range summary.Notifications() {
	fmt.Println("description:", notification.Description())
	fmt.Println("category: ", notification.RawCategory())
	fmt.Println("severity: ", notification.RawSeverityLevel())
}
Output:

Example (DisableSomeCategories)
ctx := context.Background()
driver, err := NewDriverWithContext(getUrl(), getAuth())
handleError(err)
defer handleClose(ctx, driver)

session := driver.NewSession(ctx, SessionConfig{
	// makes the server return all notification categories but deprecations
	// this overrides the driver level configuration of the same name
	NotificationsDisabledCategories: notifications.DisableCategories(notifications.Deprecation),
})

result, err := session.Run(ctx, someDeprecatedQuery(), nil)
handleError(err)

summary, err := result.Consume(ctx)
handleError(err)

// will not see the deprecation notification
for _, notification := range summary.Notifications() {
	fmt.Println("description:", notification.Description())
	fmt.Println("category: ", notification.RawCategory())
	fmt.Println("severity: ", notification.RawSeverityLevel())
}
Output:

Example (MinimumSeverityLevel)
ctx := context.Background()
driver, err := NewDriverWithContext(getUrl(), getAuth())
handleError(err)
defer handleClose(ctx, driver)

session := driver.NewSession(ctx, SessionConfig{
	// makes the server return only notifications with severity level warning or higher
	// this overrides the driver level configuration of the same name
	NotificationsMinSeverity: notifications.WarningLevel,
})

result, err := session.Run(ctx, someDeprecatedQuery(), nil)
handleError(err)

summary, err := result.Consume(ctx)
handleError(err)

// will only see notifications with severity level warning or higher
for _, notification := range summary.Notifications() {
	fmt.Println("description:", notification.Description())
	fmt.Println("category: ", notification.RawCategory())
	fmt.Println("severity: ", notification.RawSeverityLevel())
}
Output:

type SessionWithContext

type SessionWithContext interface {
	// LastBookmarks returns the bookmark received following the last successfully completed transaction.
	// If no bookmark was received or if this transaction was rolled back, the initial set of bookmarks will be
	// returned.
	LastBookmarks() Bookmarks

	// BeginTransaction starts a new explicit transaction on this session
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	BeginTransaction(ctx context.Context, configurers ...func(*TransactionConfig)) (ExplicitTransaction, error)
	// ExecuteRead executes the given unit of work in a AccessModeRead transaction with
	// retry logic in place
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	ExecuteRead(ctx context.Context, work ManagedTransactionWork, configurers ...func(*TransactionConfig)) (any, error)
	// ExecuteWrite executes the given unit of work in a AccessModeWrite transaction with
	// retry logic in place
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	ExecuteWrite(ctx context.Context, work ManagedTransactionWork, configurers ...func(*TransactionConfig)) (any, error)
	// Run executes an auto-commit statement and returns a result
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	Run(ctx context.Context, cypher string, params map[string]any, configurers ...func(*TransactionConfig)) (ResultWithContext, error)
	// Close closes any open resources and marks this session as unusable
	// Contexts terminating too early negatively affect connection pooling and degrade the driver performance.
	Close(ctx context.Context) error
	// contains filtered or unexported methods
}

SessionWithContext represents a logical connection (which is not tied to a physical connection) to the server

type Statement

type Statement interface {
	Query
}

type StatementType

type StatementType int

StatementType defines the type of the statement

const (
	// StatementTypeUnknown identifies an unknown statement type
	StatementTypeUnknown StatementType = 0
	// StatementTypeReadOnly identifies a read-only statement
	StatementTypeReadOnly StatementType = 1
	// StatementTypeReadWrite identifies a read-write statement
	StatementTypeReadWrite StatementType = 2
	// StatementTypeWriteOnly identifies a write-only statement
	StatementTypeWriteOnly StatementType = 3
	// StatementTypeSchemaWrite identifies a schema-write statement
	StatementTypeSchemaWrite StatementType = 4
)

func (StatementType) String

func (st StatementType) String() string

type Time

type Time = dbtype.Time

Aliases to simplify client usage (fewer imports) and to provide some backwards compatibility with 1.x driver.

A separate dbtype package is needed to avoid circular package references and to avoid unnecessary copying/conversions between structs since serializing/deserializing is handled within bolt package and bolt package is used from this package.

type TokenExpiredError

type TokenExpiredError = errorutil.TokenExpiredError

type Transaction

type Transaction interface {
	// Run executes a statement on this transaction and returns a result
	Run(cypher string, params map[string]any) (Result, error)
	// Commit commits the transaction
	Commit() error
	// Rollback rolls back the transaction
	Rollback() error
	// Close rolls back the actual transaction if it's not already committed/rolled back
	// and closes all resources associated with this transaction
	Close() error
}

Transaction represents a transaction in the Neo4j database Deprecated: use ExplicitTransaction instead. ExplicitTransaction is available via SessionWithContext. SessionWithContext is available via the context-aware driver/returned by NewDriverWithContext. Transaction will be removed in 6.0.

type TransactionConfig

type TransactionConfig struct {
	// Timeout is the configured transaction timeout.
	Timeout time.Duration
	// Metadata is the configured transaction metadata that will be attached to the underlying transaction.
	Metadata map[string]any
}

TransactionConfig holds the settings for explicit and auto-commit transactions. Actual configuration is expected to be done using configuration functions that are predefined, i.e. 'WithTxTimeout' and 'WithTxMetadata', or one that you could write by your own.

type TransactionExecutionLimit

type TransactionExecutionLimit = errorutil.TransactionExecutionLimit

type TransactionWork

type TransactionWork func(tx Transaction) (any, error)

TransactionWork represents a unit of work that will be executed against the provided transaction Deprecated: use ManagedTransactionWork instead. ManagedTransactionWork is created via the context-aware driver returned by NewDriverWithContext. TransactionWork will be removed in 6.0.

type UsageError

type UsageError = errorutil.UsageError

Directories

Path Synopsis
Package dbtype contains definitions of supported database types.
Package dbtype contains definitions of supported database types.
internal
bolt
Package bolt contains implementations of the database functionality.
Package bolt contains implementations of the database functionality.
connector
Package connector is responsible for connecting to a database server.
Package connector is responsible for connecting to a database server.
db
Package db defines generic database functionality.
Package db defines generic database functionality.
packstream
Package packstream handles serialization of data sent to database server and deserialization of data received from database server.
Package packstream handles serialization of data sent to database server and deserialization of data received from database server.
pool
Package pool handles the database connection pool.
Package pool handles the database connection pool.
retry
Package retry handles retry operations.
Package retry handles retry operations.
testutil
Package testutil contains shared test functionality
Package testutil contains shared test functionality
Package log defines the logging interface used internally by the driver and provides default logging implementations.
Package log defines the logging interface used internally by the driver and provides default logging implementations.
test-integration
dbserver
Package dbserver is used by integration tests to connect to databases
Package dbserver is used by integration tests to connect to databases

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL