diff --git a/code/go/example.go b/code/go/example.go index 4992f95..a9f2ea7 100644 --- a/code/go/example.go +++ b/code/go/example.go @@ -3,9 +3,9 @@ package main import ( + "context" "fmt" - "github.com/neo4j/neo4j-go-driver/v4/neo4j" - "io" + "github.com/neo4j/neo4j-go-driver/v5/neo4j" "reflect" ) @@ -19,45 +19,36 @@ func main() { } } -func runQuery(uri, database, username, password string) (result []string, err error) { - driver, err := neo4j.NewDriver(uri, neo4j.BasicAuth(username, password, "")) +func runQuery(uri, database, username, password string) (_ []string, err error) { + ctx := context.Background() + driver, err := neo4j.NewDriverWithContext(uri, neo4j.BasicAuth(username, password, "")) if err != nil { return nil, err } - defer func() {err = handleClose(driver, err)}() - session := driver.NewSession(neo4j.SessionConfig{AccessMode: neo4j.AccessModeRead, DatabaseName: database}) - defer func() {err = handleClose(session, err)}() - results, err := session.ReadTransaction(func(transaction neo4j.Transaction) (interface{}, error) { - result, err := transaction.Run( - ` - MATCH (m:Movie {title:$movieTitle})<-[:ACTED_IN]-(a:Person) RETURN a.name as actorName - `, map[string]interface{}{ - "movieTitle": "The Matrix", - }) + defer func() { err = handleClose(ctx, driver, err) }() + query := "MATCH (m:Movie {title:$movieTitle})<-[:ACTED_IN]-(a:Person) RETURN a.name as actorName" + params := map[string]any{"movieTitle": "The Matrix"} + result, err := neo4j.ExecuteQuery(ctx, driver, query, params, + neo4j.EagerResultTransformer, + neo4j.ExecuteQueryWithDatabase(database), + neo4j.ExecuteQueryWithReadersRouting()) + if err != nil { + return nil, err + } + actorNames := make([]string, len(result.Records)) + for i, record := range result.Records { + // this assumes all actors have names, hence ignoring the 2nd returned value + name, _, err := neo4j.GetRecordValue[string](record, "actorName") if err != nil { return nil, err } - var arr []string - for result.Next() { - value, found := result.Record().Get("actorName") - if found { - arr = append(arr, value.(string)) - } - } - if err = result.Err(); err != nil { - return nil, err - } - return arr, nil - }) - if err != nil { - return nil, err + actorNames[i] = name } - result = results.([]string) - return result, err + return actorNames, nil } -func handleClose(closer io.Closer, previousError error) error { - err := closer.Close() +func handleClose(ctx context.Context, closer interface{ Close(context.Context) error }, previousError error) error { + err := closer.Close(ctx) if err == nil { return previousError } diff --git a/code/go/example_aura.go b/code/go/example_aura.go index c503eaa..02d8fe5 100644 --- a/code/go/example_aura.go +++ b/code/go/example_aura.go @@ -1,34 +1,23 @@ package main + import ( + "context" "fmt" - "github.com/neo4j/neo4j-go-driver/neo4j" + "github.com/neo4j/neo4j-go-driver/v5/neo4j" ) + func main() { - var driver neo4j.Driver - var err error - // Aura requires you to use "bolt+routing" protocol, and process your queries using an encrypted connection + ctx := context.Background() + // Aura requires you to use "neo4j+s" scheme, so that your queries are processed using an encrypted connection // (You may need to replace your connection details, username and password) - boltURL := "bolt+routing://" + uri := "neo4j+s://" auth := neo4j.BasicAuth("", "", "") - - configurers := []func(*neo4j.Config){ - func (config *neo4j.Config) { - config.Encrypted = true - }, - } - if driver, err = neo4j.NewDriver(boltURL, auth, configurers...); err != nil { + driver, err := neo4j.NewDriverWithContext(uri, auth) + if err != nil { panic(err) } - // Don't forget to close the driver connection when you are finished with it - defer driver.Close() - - var writeSession neo4j.Session - // Using write transactions allow the driver to handle retries and transient errors for you - if writeSession, err = driver.Session(neo4j.AccessModeWrite); err != nil { - panic(err) - } - defer writeSession.Close() + defer closeResource(ctx, driver) // To learn more about the Cypher syntax, see https://neo4j.com/docs/cypher-manual/current/ // The Reference Card is also a good resource for keywords https://neo4j.com/docs/cypher-refcard/current/ @@ -37,52 +26,54 @@ func main() { MERGE (p2:Person { name: $person2_name }) MERGE (p1)-[:KNOWS]->(p2) RETURN p1, p2` - - var result neo4j.Result - result, err = writeSession.Run(createRelationshipBetweenPeopleQuery, map[string]interface{}{ + params := map[string]any{ "person1_name": "Alice", "person2_name": "David", - }) + } + // Using ExecuteQuery allows the driver to handle retries and transient errors for you + result, err := neo4j.ExecuteQuery(ctx, driver, createRelationshipBetweenPeopleQuery, params, + neo4j.EagerResultTransformer) if err != nil { panic(err) } - - // You should capture any errors along with the query and data for traceability - if result.Err() != nil { - panic(result.Err()) + for _, record := range result.Records { + fmt.Printf("First: '%s'\n", getPersonName(record, "p1")) + fmt.Printf("Second: '%s'\n", getPersonName(record, "p2")) } - for result.Next() { - firstPerson := result.Record().GetByIndex(0).(neo4j.Node) - fmt.Printf("First: '%s'\n", firstPerson.Props()["name"].(string)) - secondPerson := result.Record().GetByIndex(1).(neo4j.Node) - fmt.Printf("Second: '%s'\n", secondPerson.Props()["name"].(string)) - } - - var readSession neo4j.Session - - if readSession, err = driver.Session(neo4j.AccessModeRead); err != nil { - panic(err) - } - defer readSession.Close() - readPersonByName := ` MATCH (p:Person) WHERE p.name = $person_name RETURN p.name AS name` - - result, err = readSession.Run(readPersonByName, map[string]interface{}{"person_name": "Alice"}) - + result, err = neo4j.ExecuteQuery(ctx, driver, readPersonByName, map[string]any{"person_name": "Alice"}, + neo4j.EagerResultTransformer) if err != nil { panic(err) } + for _, record := range result.Records { + name, _, err := neo4j.GetRecordValue[string](record, "name") + if err != nil { + panic(err) + } + fmt.Printf("Person name: '%s' \n", name) + } +} - if result.Err() != nil { - panic(result.Err()) +func closeResource(ctx context.Context, closer interface{ Close(context.Context) error }) { + if err := closer.Close(ctx); err != nil { + panic(err) } +} - for result.Next() { - fmt.Printf("Person name: '%s' \n", result.Record().GetByIndex(0).(string)) +func getPersonName(record *neo4j.Record, key string) string { + firstPerson, _, err := neo4j.GetRecordValue[neo4j.Node](record, key) + if err != nil { + panic(err) + } + firstPersonName, err := neo4j.GetProperty[string](firstPerson, "name") + if err != nil { + panic(err) } + return firstPersonName } diff --git a/code/go/go.mod b/code/go/go.mod index d7f69b4..e43576e 100644 --- a/code/go/go.mod +++ b/code/go/go.mod @@ -1,5 +1,5 @@ module example -go 1.14 +go 1.20 -require github.com/neo4j/neo4j-go-driver v1.8.0 +require github.com/neo4j/neo4j-go-driver/v5 v5.8.0 diff --git a/code/go/go.sum b/code/go/go.sum index a47d717..a3caa35 100644 --- a/code/go/go.sum +++ b/code/go/go.sum @@ -1,34 +1,2 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/neo4j/neo4j-go-driver v1.8.0 h1:YRp9jsFcF9k/AnvbcqFCN9OMeIT2XTJgxOpp2Puq7OE= -github.com/neo4j/neo4j-go-driver v1.8.0/go.mod h1:0A49wIv0oP3uQdnbceK7Kc+snlY5B0F6dmtYArM0ltk= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +github.com/neo4j/neo4j-go-driver/v5 v5.8.0 h1:I+jtnFbbN9FvRP5etOsrdJNNEThHUCe6pO0MFk1md04= +github.com/neo4j/neo4j-go-driver/v5 v5.8.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k=