dgraph 簡介 dgraph 使用示例(基於 golang) golang client 安裝 創建 schema 數據的 CURD 事務 總結 dgraph 簡介 dgraph 是基於 golang 開發的開源的分散式圖資料庫. 誕生時間不長, 發展卻很迅速. 目前是 v20.x 版本, dg ...
dgraph 簡介
dgraph 是基於 golang 開發的開源的分散式圖資料庫. 誕生時間不長, 發展卻很迅速. 目前是 v20.x 版本, dgraph 集群主要包含 3 種節點:
- Zero: 是集群的核心, 負責調度集群伺服器和平衡伺服器組之間的數據
- Alpha: 保存數據的 謂詞 和 索引. 謂詞包括數據的 屬性 和數據之間的 關係; 索引是為了更快的進行數據的過濾和查找
- Ratel: dgraph 的 UI 介面, 可以在此界面上進行數據的 CURD, 也可以修改數據的 schema
通過增加 Alpha 的數量完成 dgraph 的水平擴展.
dgraph 是 golang 開發的, 所以部署非常簡單, 更簡單的方式是使用 docker
docker pull dgraph/dgraph:latest
然後配置一個 docker-comopse.yml, 一鍵啟動 dgraph 服務:
version: "3.2"
services:
zero:
image: dgraph/dgraph:latest
volumes:
- type: volume
source: dgraph
target: /dgraph
volume:
nocopy: true
ports:
- 5080:5080
- 6080:6080
restart: on-failure
command: dgraph zero --my=zero:5080
alpha:
image: dgraph/dgraph:latest
volumes:
- type: volume
source: dgraph
target: /dgraph
volume:
nocopy: true
ports:
- 7080:7080
- 8080:8080
- 9080:9080
restart: on-failure
command: dgraph alpha --my=alpha:7080 --lru_mb=2048 --zero=zero:5080
ratel:
image: dgraph/dgraph:latest
volumes:
- type: volume
source: dgraph
target: /dgraph
volume:
nocopy: true
ports:
- 8000:8000
command: dgraph-ratel
volumes:
dgraph:
啟動 dgraph, 在上面 docker-compose.yml 相同的文件夾下執行:
docker-compose up -d
如果沒有錯誤, 可以通過: http://<YOUR IP/Domain>:8000/ 來訪問 draph 的 UI 界面.
dgraph 使用示例(基於 golang)
通過 dgraph 的 UI 界面, 可以完成所有的操作, 但要想將 dgraph 和應用結合, 還得使用 dgraph 的 SDK.
dgraph 的 SDK 支持各種語言, 官方支持的主要有: Go, C#, Java, Javascript, Python.
dgraph 本身就是基於 golang 開發的, 所以對 Go 的支持肯定最全面, 下麵就使用 golang 的 client 來演示 dgraph 的操作.
golang client 安裝
安裝最新版的 client:
go get github.com/dgraph-io/dgo/v200
創建 schema
代碼:
1 func NewDgraphClient() *dgo.Dgraph {
2 conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
3 if err != nil {
4 log.Fatal(err)
5 }
6
7 client := dgo.NewDgraphClient(api.NewDgraphClient(conn))
8
9 return client
10 }
11
12 func CreateSchema(client *dgo.Dgraph) error {
13 schema := `
14 name: string @index(term) .
15 age: int .
16
17 type Person {
18 name
19 age
20 }
21 `
22 op := &api.Operation{Schema: schema}
23
24 err := client.Alter(context.Background(), op)
25 return err
26 }
執行成功後, 在 UI 界面(http://localhost:8000)上驗證是否創建成功:
schema(pred:[name, age]) {
perdicate
type
index
}
結果如下:
{
"data": {
"schema": [
{
"predicate": "age",
"type": "int"
},
{
"predicate": "name",
"type": "string",
"index": true
}
]
},
... 省略 ...
}
數據的 CURD
首先, 新增數據
1 type Person struct {
2 Uid string `json:"uid"`
3 Name string `json:"name"`
4 Age int `json:"age"`
5 Friends []Person `json:"friends"`
6 }
7
8 func AddSomeData(client *dgo.Dgraph) error {
9 p1 := &Person{
10 Name: "Dog",
11 Age: 10,
12 }
13 p1.Friends = make([]Person, 0)
14
15 p2 := &Person{
16 Name: "Monkey",
17 Age: 20,
18 }
19 p3 := &Person{
20 Name: "Cat",
21 Age: 30,
22 }
23
24 p1.Friends = append(p1.Friends, *p2)
25 p1.Friends = append(p1.Friends, *p3)
26
27 mu := &api.Mutation{CommitNow: true}
28 pb, err := json.Marshal(p1)
29 if err != nil {
30 return err
31 }
32
33 mu.SetJson = pb
34 _, err = client.NewTxn().Mutate(context.Background(), mu)
35 return err
36 }
查詢數據:
1 func QueryData(client *dgo.Dgraph) error {
2 q := `
3 query q($name: string){
4 q(func:allofterms(name, $name)){
5 name
6 age
7 uid
8 friends{
9 name
10 age
11 uid
12 }
13 }
14 }
15 `
16 txn := client.NewTxn()
17 res, err := txn.QueryWithVars(context.Background(), q, map[string]string{"$name": "Dog"})
18 if err != nil {
19 return err
20 }
21 fmt.Println(res.String())
22 return nil
23 }
為了簡化, 返回值中我直接列印了 string 格式, 其實返回的是個 json 結構.
可以看出, 返回值中包含了上一步創建的 3 個 Person, 其中 2 個作為 Dog 的 friends 返回的.
更新數據:
1 func UpdateData(client *dgo.Dgraph) error {
2 mu := &api.Mutation{
3 CommitNow: true,
4 SetNquads: []byte(`<0xfffd8d67d832b975> <age> "12" .`),
5 }
6
7 _, err := client.NewTxn().Mutate(context.Background(), mu)
8 return err
9 }
其中 <0xfffd8d67d832b975> 是數據的 uid, 根據上面 query 示例的返回值中可以查找到.
這裡需要註意的是,
刪除數據(刪除數據的一個屬性):
1 func DeleteProp(client *dgo.Dgraph) error {
2 mu := &api.Mutation{
3 CommitNow: true,
4 DelNquads: []byte(`<0xfffd8d67d832b976> <age> * .`),
5 }
6
7 _, err := client.NewTxn().Mutate(context.Background(), mu)
8 return err
9 }
刪除了 <0xfffd8d67d832b976> 這條數據的
將數據的屬性和關係都刪除之後, 這條數據就相當於刪除了.
直接根據 Uid 刪除數據的 api 也有, 但是使用後無效(具體我提了個 issue 到 dgraph 的代碼庫)
事務
draph 是支持事務的, 上面的例子中其實已經使用了事務, 只不過每個事務中只有一個操作.
如果有多個操作, 類似下麵這樣的代碼即可:
1 ctx := context.Background()
2 tnx := client.NewTxn()
3
4 _, err := tnx.Mutate(ctx, mu1)
5 if err != nil {
6 tnx.Discard(ctx)
7 }
8 _, err = tnx.Mutate(ctx, mu2)
9 if err != nil {
10 tnx.Discard(ctx)
11 }
12
13 tnx.Commit(ctx)
總結
圖資料庫不是萬能的, 它的目的也不是取代關係資料庫.
我們根據使用場景在合適的時候選用 dgraph, 可以更加的輕鬆的完成數據分析, 而不用深陷 sql 的坑中.