Skip to content

Commit f66f943

Browse files
authored
Update README with 5.0 examples and clearer instructions
* Remove tag from `go get` instructions * Generalize migration wording * Update main code snippet to 5.0 API * Document server / driver version matrix Do not mark 5.0 as EOL yet since it's not publicly out. * Emphasize required Go version * Favour any over verbose interface{} * Reformat tables
1 parent 332277b commit f66f943

File tree

1 file changed

+112
-83
lines changed

1 file changed

+112
-83
lines changed

README.md

Lines changed: 112 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ This is the official Neo4j Go Driver.
44

55
## Getting the Driver
66

7+
### Go version prerequisites
8+
9+
The Go driver only works with actively maintained Go versions.
10+
11+
Read [Go official release policy](https://go.dev/doc/devel/release#policy) to learn more.
12+
713
### Module version
814

915
Make sure your application has been set up to use go modules (there should be a go.mod file in your application root).
@@ -13,36 +19,34 @@ Make sure your application has been set up to use go modules (there should be a
1319
Add the driver with:
1420

1521
```shell
16-
go get github.com/neo4j/neo4j-go-driver/v5@<the 5.x tag>
22+
go get github.com/neo4j/neo4j-go-driver/v5
1723
```
1824

1925
#### 4.x
2026

2127
Add the driver with:
2228

2329
```shell
24-
go get github.com/neo4j/neo4j-go-driver/v4@<the 4.x tag>
30+
go get github.com/neo4j/neo4j-go-driver/v4
2531
```
2632

2733
#### 1.x
2834

2935
For versions 1.x of the driver (notice the absence of `/v4` or `/v5`), run instead the following:
3036

3137
```shell
32-
go get github.com/neo4j/neo4j-go-driver@<the 1.x tag>
38+
go get github.com/neo4j/neo4j-go-driver
3339
```
3440

3541
## Documentation
3642

3743
Drivers manual that describes general driver concepts in depth [here](https://neo4j.com/docs/driver-manual/5.0/).
3844
Go package API documentation [here](https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v5).
3945

40-
## Migrating from 1.x and 4.x
46+
## Migrating from previous versions
4147

4248
See [migration guide](MIGRATION_GUIDE.md) for information on how to migrate
43-
from 1.8 (and 1.7) version of the driver.
44-
45-
This also includes a section on how migrate from 4.x to 5.0.
49+
from previous versions of the driver to the current one.
4650

4751
## Minimum Viable Snippet
4852

@@ -54,77 +58,101 @@ Make sure to use the configuration in the code that matches the version of Neo4j
5458
package main
5559

5660
import (
57-
"fmt"
58-
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
59-
"io"
60-
"log"
61+
"context"
62+
"fmt"
63+
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
64+
"io"
65+
"log"
6166
)
6267

6368
func main() {
6469
// Neo4j 4.0, defaults to no TLS therefore use bolt:// or neo4j://
6570
// Neo4j 3.5, defaults to self-signed certificates, TLS on, therefore use bolt+ssc:// or neo4j+ssc://
6671
dbUri := "neo4j://localhost:7687"
67-
driver, err := neo4j.NewDriver(dbUri, neo4j.BasicAuth("username", "password", ""))
72+
driver, err := neo4j.NewDriverWithContext(dbUri, neo4j.BasicAuth("username", "password", ""))
6873
if err != nil {
6974
panic(err)
7075
}
76+
// Starting with 5.0, you can control the execution of most driver APIs
77+
// To keep things simple, we create here a never-cancelling context
78+
// Read https://pkg.go.dev/context to learn more about contexts
79+
ctx := context.Background()
7180
// Handle driver lifetime based on your application lifetime requirements driver's lifetime is usually
7281
// bound by the application lifetime, which usually implies one driver instance per application
73-
defer driver.Close()
74-
item, err := insertItem(driver)
82+
// Make sure to handle errors during deferred calls
83+
defer driver.Close(ctx)
84+
item, err := insertItem(ctx, driver)
7585
if err != nil {
7686
panic(err)
7787
}
7888
fmt.Printf("%v\n", item)
7989
}
8090

81-
func insertItem(driver neo4j.Driver) (*Item, error) {
82-
// Sessions are short-lived, cheap to create and NOT thread safe. Typically create one or more sessions
83-
// per request in your web application. Make sure to call Close on the session when done.
84-
// For multi-database support, set sessionConfig.DatabaseName to requested database
85-
// Session config will default to write mode, if only reads are to be used configure session for
86-
// read mode.
87-
session := driver.NewSession(neo4j.SessionConfig{})
88-
defer session.Close()
89-
result, err := session.WriteTransaction(createItemFn)
90-
if err != nil {
91-
return nil, err
92-
}
93-
return result.(*Item), nil
91+
func insertItem(ctx context.Context, driver neo4j.DriverWithContext) (*Item, error) {
92+
// Sessions are short-lived, cheap to create and NOT thread safe. Typically create one or more sessions
93+
// per request in your web application. Make sure to call Close on the session when done.
94+
// For multi-database support, set sessionConfig.DatabaseName to requested database
95+
// Session config will default to write mode, if only reads are to be used configure session for
96+
// read mode.
97+
session := driver.NewSession(ctx, neo4j.SessionConfig{})
98+
defer session.Close(ctx)
99+
result, err := session.ExecuteWrite(ctx, createItemFn(ctx))
100+
if err != nil {
101+
return nil, err
102+
}
103+
return result.(*Item), nil
94104
}
95105

96-
func createItemFn(tx neo4j.Transaction) (interface{}, error) {
97-
records, err := tx.Run("CREATE (n:Item { id: $id, name: $name }) RETURN n.id, n.name", map[string]interface{}{
98-
"id": 1,
99-
"name": "Item 1",
100-
})
101-
// In face of driver native errors, make sure to return them directly.
102-
// Depending on the error, the driver may try to execute the function again.
103-
if err != nil {
104-
return nil, err
105-
}
106-
record, err := records.Single()
107-
if err != nil {
108-
return nil, err
109-
}
110-
// You can also retrieve values by name, with e.g. `id, found := record.Get("n.id")`
111-
return &Item{
112-
Id: record.Values[0].(int64),
113-
Name: record.Values[1].(string),
114-
}, nil
106+
func createItemFn(ctx context.Context) neo4j.ManagedTransactionWork {
107+
return func(tx neo4j.ManagedTransaction) (any, error) {
108+
records, err := tx.Run(ctx, "CREATE (n:Item { id: $id, name: $name }) RETURN n.id, n.name", map[string]any{
109+
"id": 1,
110+
"name": "Item 1",
111+
})
112+
// In face of driver native errors, make sure to return them directly.
113+
// Depending on the error, the driver may try to execute the function again.
114+
if err != nil {
115+
return nil, err
116+
}
117+
record, err := records.Single(ctx)
118+
if err != nil {
119+
return nil, err
120+
}
121+
// You can also retrieve values by name, with e.g. `id, found := record.Get("n.id")`
122+
return &Item{
123+
Id: record.Values[0].(int64),
124+
Name: record.Values[1].(string),
125+
}, nil
126+
}
115127
}
116128

117129
type Item struct {
118-
Id int64
119-
Name string
130+
Id int64
131+
Name string
120132
}
121133
```
122134

123135
## Neo4j and Bolt protocol versions
124136

125-
The driver implements Bolt protocol version 3. This means that either Neo4j server 3.5 or above can be used with the driver.
126-
127-
Neo4j server 4 supports both Bolt protocol version 3 and version 4.
137+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
138+
| Server \\ Driver | 1.7 | 4.0 | 4.1 | 4.2 | 4.3 | *4.4* | 5.0 | *5.1* |
139+
+==================+=======+=======+=======+=======+=======+=======+=======+=======+
140+
| Neo4j 3.5 (EOL) | Yes | Yes | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
141+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
142+
| Neo4j 4.0 (EOL) | Yes | Yes | Yes | Yes | Yes | Yes | (Yes) | (Yes) |
143+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
144+
| Neo4j 4.1 (EOL) | ? | Yes | Yes | Yes | Yes | Yes | (Yes) | (Yes) |
145+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
146+
| Neo4j 4.2 (EOL) | ? | ? | Yes | Yes | Yes | Yes | (Yes) | (Yes) |
147+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
148+
| Neo4j 4.3 | ? | ? | ? | Yes | Yes | Yes | (Yes) | (Yes) |
149+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
150+
| Neo4j 4.4 (LTS) | ? | ? | ? | ? | Yes | Yes | Yes | Yes |
151+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
152+
| Neo4j 5.0 | ? | ? | ? | ? | ? | Yes | Yes | Yes |
153+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
154+
| Neo4j 5.1 | ? | ? | ? | ? | ? | ? | Yes | Yes |
155+
+------------------+-------+-------+-------+-------+-------+-------+-------+-------+
128156

129157
## Connecting to a causal cluster
130158

@@ -149,7 +177,7 @@ The records inside the result can be accessed via `Next()`/`Record()` functions
149177

150178
```go
151179
// Next returns false upon error
152-
for result.Next() {
180+
for result.Next(ctx) {
153181
record := result.Record()
154182
handleRecord(record)
155183
}
@@ -160,7 +188,8 @@ The records inside the result can be accessed via `Next()`/`Record()` functions
160188
```
161189

162190
### Accessing Values in a Record
163-
Values in a `Record` can be accessed either by index or by alias. The return value is an `interface{}` which means you need to convert the interface to the type expected
191+
Values in a `Record` can be accessed either by index or by alias. The return value is an `any` which means you need
192+
to convert the interface to the expected type
164193

165194
```go
166195
value := record.Values[0]
@@ -174,31 +203,31 @@ if value, ok := record.Get('field_name'); ok {
174203
```
175204

176205
### Value Types
177-
The driver exposes values in the record as an `interface{}` type.
206+
The driver exposes values in the record as an `any` type.
178207
The underlying types of the returned values depend on the corresponding Cypher types.
179208

180209
The mapping between Cypher types and the types used by this driver (to represent the Cypher type):
181210

182-
| Cypher Type | Driver Type
183-
| ---: | :--- |
184-
| *null* | nil |
185-
| List | []interface{} |
186-
| Map | map[string]interface{} |
187-
| Boolean| bool |
188-
| Integer| int64 |
189-
| Float| float |
190-
| String| string |
191-
| ByteArray| []byte |
192-
| Node| neo4j.Node |
193-
| Relationship| neo4j.Relationship |
194-
| Path| neo4j.Path |
211+
| Cypher Type | Driver Type |
212+
|-------------:|:-----------------------|
213+
| *null* | nil |
214+
| List | []any |
215+
| Map | map[string]any |
216+
| Boolean | bool |
217+
| Integer | int64 |
218+
| Float | float |
219+
| String | string |
220+
| ByteArray | []byte |
221+
| Node | neo4j.Node |
222+
| Relationship | neo4j.Relationship |
223+
| Path | neo4j.Path |
195224

196225
### Spatial Types - Point
197226

198-
| Cypher Type | Driver Type
199-
| ---: | :--- |
200-
| Point| neo4j.Point2D |
201-
| Point| neo4j.Point3D |
227+
| Cypher Type | Driver Type |
228+
|------------:|:--------------|
229+
| Point | neo4j.Point2D |
230+
| Point | neo4j.Point3D |
202231

203232
The temporal types are introduced in Neo4j 3.4 series.
204233

@@ -224,14 +253,14 @@ The temporal types are introduced in Neo4j 3.4 series. Given the fact that datab
224253

225254
The mapping among the Cypher temporal types and actual exposed types are as follows:
226255

227-
| Cypher Type | Driver Type |
228-
| :----------: | :-----------: |
229-
| Date | neo4j.Date |
230-
| Time | neo4j.OffsetTime |
231-
| LocalTime| neo4j.LocalTime |
232-
| DateTime | time.Time |
256+
| Cypher Type | Driver Type |
257+
|:-------------:|:-------------------:|
258+
| Date | neo4j.Date |
259+
| Time | neo4j.OffsetTime |
260+
| LocalTime | neo4j.LocalTime |
261+
| DateTime | time.Time |
233262
| LocalDateTime | neo4j.LocalDateTime |
234-
| Duration | neo4j.Duration |
263+
| Duration | neo4j.Duration |
235264

236265

237266
Receiving a temporal value as driver type:
@@ -285,9 +314,9 @@ The `Log` field of the `neo4j.Config` struct is defined to be of interface `neo4
285314
```go
286315
type Logger interface {
287316
Error(name string, id string, err error)
288-
Warnf(name string, id string, msg string, args ...interface{})
289-
Infof(name string, id string, msg string, args ...interface{})
290-
Debugf(name string, id string, msg string, args ...interface{})
317+
Warnf(name string, id string, msg string, args ...any)
318+
Infof(name string, id string, msg string, args ...any)
319+
Debugf(name string, id string, msg string, args ...any)
291320
}
292321
```
293322

@@ -316,8 +345,8 @@ The `BoltLogger` field of the `neo4j.SessionConfig` struct is defined to be of i
316345

317346
```go
318347
type BoltLogger interface {
319-
LogClientMessage(context string, msg string, args ...interface{})
320-
LogServerMessage(context string, msg string, args ...interface{})
348+
LogClientMessage(context string, msg string, args ...any)
349+
LogServerMessage(context string, msg string, args ...any)
321350
}
322351
```
323352

0 commit comments

Comments
 (0)