数据类型和 Cypher 类型映射
本节中的表格显示了 Cypher 数据类型与 Go 类型之间的映射关系。
当访问记录的内容时,其所有属性都为 any 类型。这意味着如果您想要使用在这些类型上定义的方法/功能,则必须将其强制转换为相关的 Go 类型。例如,如果来自数据库的 name 属性是字符串,则 record.AsMap()["name"][1] 会在编译时导致无效操作错误。为了使其工作,在使用它作为字符串之前将其强制转换为字符串:name := record.AsMap()["name"].(string) ,然后 name[1] 。 |
核心类型
Cypher 类型 | Go 类型 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
时间类型
驱动程序提供了一组符合 ISO-8601 和 Cypher 的时间数据类型。亚秒值以纳秒精度测量。
驱动程序的类型依赖于 Go 的 time
类型。除 neo4j.Duration
外,所有时间类型实际上都是 time.Date
对象。
-
如果您想查询数据库中的时间类型,请实例化一个
time.Date
对象并将其用作查询参数(即,您无需关心驱动程序的类型)。 -
如果您从
time.Date
对象检索之前插入的时间对象,您将获得time.Date
对象(即,您无需关心驱动程序的类型)。 -
如果您使用 Cypher 时间函数 中的任何一个接收时间对象,您将获得下表中所示的相应驱动程序类型。您随后可以使用
.Time()
将它们转换为 Gotime.Date
对象。Cypher 类型 Go 类型 DATE
neo4j.Date
ZONED TIME
neo4j.OffsetTime
LOCAL TIME
neo4j.LocalTime
ZONED DATETIME
neo4j.Time
LOCAL DATETIME
neo4j.LocalDateTime
DURATION
neo4j.Duration
package main
import (
"fmt"
"context"
"time"
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
"reflect"
)
func main() {
ctx := context.Background()
// Connection to database
dbUri := "<URI for Neo4j database>"
dbUser := "<Username>"
dbPassword := "<Password>"
driver, _ := neo4j.NewDriverWithContext(
dbUri,
neo4j.BasicAuth(dbUser, dbPassword, ""))
driver.VerifyConnectivity(ctx)
// Define a date, with timezone
location, _ := time.LoadLocation("Europe/Stockholm")
friendsSince := time.Date(2006, time.December, 16, 13, 59, 59, 999999999, location)
result, err := neo4j.ExecuteQuery(ctx, driver, `
MERGE (a:Person {name: $name})
MERGE (b:Person {name: $friend})
MERGE (a)-[friendship:KNOWS {since: $friendsSince}]->(b)
RETURN friendship.since AS date
`, map[string]any{
"name": "Alice",
"friend": "Bob",
"friendsSince": friendsSince,
}, neo4j.EagerResultTransformer,
neo4j.ExecuteQueryWithDatabase("neo4j"))
if err != nil {
panic(err)
}
date, _ := result.Records[0].Get("date")
fmt.Println(reflect.TypeOf(date)) // time.Time
fmt.Println(date) // 2006-12-16 13:59:59.999999999 +0200 EET
}
package main
import (
"fmt"
"context"
"time"
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
"reflect"
)
func main() {
ctx := context.Background()
// Connection to database
dbUri := "<URI for Neo4j database>"
dbUser := "<Username>"
dbPassword := "<Password>"
driver, _ := neo4j.NewDriverWithContext(
dbUri,
neo4j.BasicAuth(dbUser, dbPassword, ""))
driver.VerifyConnectivity(ctx)
// Query and return a neo4j.Time object
result, err := neo4j.ExecuteQuery(ctx, driver, `
MERGE (a:Person {name: $name})
MERGE (b:Person {name: $friend})
MERGE (a)-[friendship:KNOWS {since: time()}]->(b)
RETURN friendship.since AS time
`, map[string]any{
"name": "Alice",
"friend": "Sofia",
}, neo4j.EagerResultTransformer,
neo4j.ExecuteQueryWithDatabase("neo4j"))
if err != nil {
panic(err)
}
time, _ := result.Records[0].Get("time")
fmt.Println(reflect.TypeOf(time)) // time.Time
castDate, _ := time.(neo4j.Time) // cast from `any` to `neo4j.Time`
fmt.Println(castDate.Time()) // -0001-11-30 12:18:08.973 +0000 Offset
}
Duration
表示两个时间点之间的差值。
duration := neo4j.Duration{
Months: 1,
Days: 2,
Seconds: 3,
Nanos: 4,
}
fmt.Println(duration) // 'P1Y2DT3.000000004S'
有关完整文档,请参阅 API 文档 → Duration。
空间类型
Cypher 支持 空间值(点),Neo4j 可以将这些点值存储为节点和关系上的属性。
对象属性 SpatialRefId
(空间参考标识符的缩写)是一个数字,用于识别要解释空间类型的坐标系。您可以将其视为每个空间类型的唯一标识符。
Cypher 类型 | Go 类型 | SpatialRefId |
---|---|---|
|
|
7203 |
|
|
4326 |
|
|
9157 |
|
|
4979 |
空间类型在 dbtype 包中实现,因此实际类型为 dbtype.Point2D/3D 。但是,它们也导入到主 neo4j 包中,因此它们也可以用作 neo4j.Point2D/3D 。 |
Point2D
Point2D
类型可用于表示二维笛卡尔点或二维世界大地测量系统 (WGS84) 点,具体取决于 SpatialRefId
的值。
// A 2D Cartesian Point
cartesian2d := neo4j.Point2D{
X: 1.23,
Y: 4.56,
SpatialRefId: 7203,
}
fmt.Println(cartesian2d)
// Point{srId=7203, x=1.230000, y=4.560000}
// A 2D WGS84 Point
wgs842d := neo4j.Point2D{
X: 1.23,
Y: 4.56,
SpatialRefId: 9157,
}
fmt.Println(wgs842d)
// Point{srId=9157, x=1.230000, y=4.560000}
Point3D
Point3D
类型可用于表示三维笛卡尔点或三维世界大地测量系统 (WGS84) 点,具体取决于 SpatialRefId
的值。
// A 3D Cartesian Point
cartesian3d := neo4j.Point3D{
X: 1.23,
Y: 4.56,
Z: 7.89,
SpatialRefId: 9157,
}
fmt.Println(cartesian3d)
// Point{srId=9157, x=1.230000, y=4.560000, z=7.890000}
// A 3D WGS84 Point
wgs843d := neo4j.Point3D{
X: 1.23,
Y: 4.56,
Z: 7.89,
SpatialRefId: 4979,
}
fmt.Println(wgs843d)
// Point{srId=4979, x=1.230000, y=4.560000, z=7.890000}
图形类型
图形类型仅作为查询结果返回,不能用作参数.
Cypher 类型 | Python 类型 |
---|---|
|
|
|
|
|
|
Node
表示图中的节点。
属性 ElementId
包含实体的数据库内部标识符。应谨慎使用此标识符,因为不保证在单个事务范围之外 id 值与元素之间的映射关系。换句话说,使用 ElementId
在不同事务中 MATCH
元素是有风险的。
result, err := neo4j.ExecuteQuery(ctx, driver, `
MERGE (p:Person {name: $name}) RETURN p AS person, p.name as name
`, map[string]any{
"name": "Alice",
}, neo4j.EagerResultTransformer,
neo4j.ExecuteQueryWithDatabase("neo4j"))
if err != nil {
panic(err)
}
node, _ := result.Records[0].AsMap()["person"].(neo4j.Node)
fmt.Println("Node ID:", node.ElementId)
fmt.Println("Node labels:", node.Labels)
fmt.Println("Node properties:", node.Props)
// Node ID: 4:2691aa68-87cc-467d-9d09-431df9f5c456:0
// Node labels: [Person]
// Node properties: map[name:Alice]
有关完整文档,请参阅 API 文档 → Node。
Relationship
表示图中的关系。
属性 ElementId
包含实体的数据库内部标识符。应谨慎使用此标识符,因为不保证在单个事务范围之外 id 值与元素之间的映射关系。
result, err := neo4j.ExecuteQuery(ctx, driver, `
MERGE (p:Person {name: $name})
MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend:Person {name: $friendName})
RETURN r AS friendship
`, map[string]any{
"name": "Alice",
"status": "BFF",
"friendName": "Bob",
}, neo4j.EagerResultTransformer,
neo4j.ExecuteQueryWithDatabase("neo4j"))
if err != nil {
panic(err)
}
relationship, _ := result.Records[0].AsMap()["friendship"].(neo4j.Relationship)
fmt.Println("Relationship ID:", relationship.ElementId)
fmt.Println("Relationship type:", relationship.Type)
fmt.Println("Relationship properties:", relationship.Props)
fmt.Println("Relationship start elID:", relationship.StartElementId)
fmt.Println("Relationship end elID:", relationship.EndElementId)
// Relationship ID: 5:2691aa68-87cc-467d-9d09-431df9f5c456:0
// Relationship type: KNOWS
// Relationship properties: map[since:{0 63824025600 <nil>} status:BFF]
// Relationship start elID: 4:2691aa68-87cc-467d-9d09-431df9f5c456:0
// Relationship end elID: 4:2691aa68-87cc-467d-9d09-431df9f5c456:1
有关完整文档,请参阅 API 文档 → Relationship。
Path
表示图中的路径。
package main
import (
"fmt"
"context"
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
)
func main() {
ctx := context.Background()
// Connection to database
dbUri := "<URI for Neo4j database>"
dbUser := "<Username>"
dbPassword := "<Password>"
driver, _ := neo4j.NewDriverWithContext(
dbUri,
neo4j.BasicAuth(dbUser, dbPassword, ""))
driver.VerifyConnectivity(ctx)
// Create some :Person nodes linked by :KNOWS relationships
addFriend(ctx, driver, "Alice", "BFF", "Bob")
addFriend(ctx, driver, "Bob", "Fiends", "Sofia")
addFriend(ctx, driver, "Sofia", "Acquaintances", "Sofia")
// Follow :KNOWS relationships outgoing from Alice three times, return as path
result, err := neo4j.ExecuteQuery(ctx, driver, `
MATCH path=(:Person {name: $name})-[:KNOWS*3]->(:Person)
RETURN path AS friendshipChain
`, map[string]any{
"name": "Alice",
}, neo4j.EagerResultTransformer,
neo4j.ExecuteQueryWithDatabase("neo4j"))
if err != nil {
panic(err)
}
path := result.Records[0].AsMap()["friendshipChain"].(neo4j.Path)
fmt.Println("-- Path breakdown --")
for i := range path.Relationships {
name := path.Nodes[i].Props["name"]
status := path.Relationships[i].Props["status"]
friendName := path.Nodes[i+1].Props["name"]
fmt.Printf("%s is friends with %s (%s)\n", name, friendName, status)
}
}
func addFriend(ctx context.Context, driver neo4j.DriverWithContext, name string, status string, friendName string) {
_, err := neo4j.ExecuteQuery(ctx, driver, `
MERGE (p:Person {name: $name})
MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend:Person {name: $friendName})
`, map[string]any{
"name": name,
"status": status,
"friendName": friendName,
}, neo4j.EagerResultTransformer,
neo4j.ExecuteQueryWithDatabase("neo4j"))
if err != nil {
panic(err)
}
}
有关完整文档,请参阅 API 文档 → Path。
异常
在大多数情况下,驱动程序只是转发服务器可能引发的任何错误。有关服务器可以返回的错误列表,请参阅 状态代码 页面。
某些服务器错误被标记为可以安全地重试,而无需更改原始请求。此类错误的示例包括死锁、内存问题或连接问题。当引发错误时,函数 neo4j.IsRetryable(error)
会提供有关后续尝试是否可能成功的见解。这在使用 显式事务 运行查询时尤其有用,以便了解失败的查询是否应该再次运行。请注意,托管事务 已经实现了重试机制,因此您无需实现自己的重试机制。
词汇表
- LTS
-
长期支持版本是指保证支持多年的版本。Neo4j 4.4 是 LTS,Neo4j 5 也将具有 LTS 版本。
- Aura
-
Aura 是 Neo4j 的完全托管云服务。它提供免费和付费计划。
- Cypher
-
Cypher 是 Neo4j 的图查询语言,允许您从数据库中检索数据。它类似于 SQL,但适用于图。
- APOC
-
Awesome Procedures On Cypher (APOC) 是一个包含(许多)函数的库,这些函数无法轻松地用 Cypher 本身表达。
- Bolt
-
Bolt 是 Neo4j 实例和驱动程序之间交互使用的协议。默认情况下,它监听端口 7687。
- ACID
-
原子性、一致性、隔离性、持久性 (ACID) 是保证数据库事务可靠处理的属性。符合 ACID 的 DBMS 确保数据库中的数据即使在发生故障的情况下也能保持准确性和一致性。
- 最终一致性
-
如果数据库提供了以下保证,则它是最终一致的:所有集群成员将在 *某个时间点* 存储数据的最新版本。
- 因果一致性
-
如果每个集群成员都以相同的顺序看到读写查询,则数据库是因果一致的。这比 *最终一致性* 更强大。
- NULL
-
空标记不是一种类型,而是值不存在的占位符。有关更多信息,请参阅 Cypher → 使用
null
。 - 事务
-
事务是工作单元,要么 *完全提交*,要么在失败时 *回滚*。例如,银行转账:它涉及多个步骤,但这些步骤必须 *全部* 成功或回滚,以避免从一个账户中扣款但没有添加到另一个账户中。
- 背压
-
背压是阻止数据流的力。它确保客户端不会被数据淹没,而数据流的速度超过了客户端的处理能力。
- 事务函数
-
事务函数是在
ExecuteRead
或ExecuteWrite
调用执行的回调。如果发生服务器故障,驱动程序会自动重新执行回调。 - DriverWithContext
-
一个
DriverWithContext
对象包含与 Neo4j 数据库建立连接所需的所有详细信息。