#前面已經分享過以 HTTP API 或 JavaScript driver 開發 Neo4j 前端應用,今天我們就來看後端應用囉,這篇文章會以 Golang 語言為參考。
目前(2020/10) Neo4j 官方支援的程式語言有 Java、 .NET、JavaScript、Python、Go,針對 Java 還有額外支援框架 Spring、Neo4j-OGM。
其他語言如 Ruby、PHP、Erlang/Elixir、Perl、C/C++、Clojure、Haskell、R 則都是 Neo4j 社區中的開發者們所貢獻,但也都有收錄在官方教學
安裝 Golang driver for Neo4j
使用 go get 或 GO Module 管理 package,建議後者。
go get github.com/neo4j/neo4j-go-driver/neo4j
go mod init github.com/eggttball/go-neo4j
go mod edit -require github.com/neo4j/neo4j-go-driver@v1.8.3
Import neo4j driver
import "github.com/neo4j/neo4j-go-driver/neo4j"
宣告 Neo4j driver 物件
driver
session
create driver and session
driver, err := neo4j.NewDriver("bolt://localhost:7687", neo4j.BasicAuth("neo4j", password, ""), func(c *neo4j.Config) {
c.Encrypted = encrypted
})
if err != nil {
return "", err
}
defer driver.Close()
session, err := driver.Session(neo4j.AccessModeWrite)
if err != nil {
return "", err
}
defer session.Close()
這邊指定的 Access Mode Read/Write 有助於在連線因果叢集時,讓叢集決定要將 Cypher 查詢指派給 Core server 還是 Replica server,正確的設定 Access Mode 將有助於資料庫的效能大幅提升。
不過在 Session 初始化時的 Access Mode 只會影響自動交易,如果是手動交易,Access Mode 最終還是取決於 Session.WriteTransaction 或是 Session.ReadTransaction。
自動 Commit 的交易
Session.Run
Result.Consume 會一次讀取所有的回傳資料並回傳 Summary
result, err := session.Run("CREATE (a:Person {name: $name})", map[string]interface{}{"name":
name})
if err != nil {
return err
}
if _, err = result.Consume(); err != nil {
return err
}
手動交易
greeting, err := session.WriteTransaction(func(transaction neo4j.Transaction) (interface{}, error) {
result, err := transaction.Run(
"CREATE (a:Greeting) SET a.message = $message RETURN a.message + ', from node ' + id(a)",
map[string]interface{}{"message": "hello, world"})
if err != nil {
return nil, err
}
if result.Next() {
return result.Record().GetByIndex(0), nil
}
return nil, result.Err()
})
這邊用到了 Result.Next() 來確認是否有回傳結果,以及 Result.Record() 來取得每一筆資料
如果預期回傳的資料有多筆,可以這樣寫。
for result.Next() {
record = result.Record();
if value, ok := record.Get('field_name'); ok {
// a value with alias field_name was found
// process value
}
}
以上也刻意示範了 Get by index 和 Get by field name 的選擇作法
Cypher 與 Golang driver 的資料型別對應
從資料庫取得的結果都會是 interface{} 型別,在程式碼中的操作很不便,但我們可以把它 UnBoxing 成真正的物件型別,列表如下
Cypher Type | Driver Type |
---|---|
null | nil |
List | []interface{} |
Map | map[string]interface{} |
Boolean | bool |
Integer | int64 |
Float | float |
String | string |
ByteArray | []byte |
Node | neo4j.Node |
Relationship | neo4j.Relationship |
Path | neo4j.Path |
Point | neo4j.Point |
Date | neo4j.Date |
Time | neo4j.OffsetTime |
LocalTime | neo4j.LocalTime |
DateTime | time.Time |
LocalDateTime | neo4j.LocalDateTime |
Duration | neo4j.Duration |
例如
value, ok := record.Get('birthday').(neo4j.Date)
連線因果叢集
如果資料庫是採用因果叢集架構,只需要將協定改成 bolt+routing 中可,後面接的機器位址則必須是任一台 Core Server。
if driver, err = neo4j.NewDriver("bolt+routing://localhost:7687", neo4j.BasicAuth("username", "password", "")); err != nil {
return err
}
資考資源:
https://github.com/neo4j/neo4j-go-driver
https://neo4j.com/docs/pdf/neo4j-driver-manual-1.7-go.pdf
https://godoc.org/github.com/neo4j/neo4j-go-driver/neo4j