- dgraph 简介
- dgraph 使用示例(基于 golang)
- golang client 安装
- 创建 schema
- 数据的 CURD
- 事务
- 总结
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-ratelvolumes: dgraph:
启动 dgraph, 在上面 docker-compose.yml 相同的文件夹下执行:
docker-compose up -d
如果没有错误, 可以通过: 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 client10 }11 12 func CreateSchema(client *dgo.Dgraph) error {13 schema := `14 name: string @index(term) .15 age: int .16 17 type Person {18 name19 age20 }21 `22 op := &api.Operation{Schema: schema}23 24 err := client.Alter(context.Background(), op)25 return err26 }
执行成功后, 在 UI 界面 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 err31 }32 33 mu.SetJson = pb34 _, err = client.NewTxn().Mutate(context.Background(), mu)35 return err36 }
查询数据:
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 name10 age11 uid12 }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 err20 }21 fmt.Println(res.String())22 return nil23 }
为了简化, 返回值中我直接打印了 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 err9 }
其中 <0xfffd8d67d832b975> 是数据的 uid, 根据上面 query 示例的返回值中可以查找到.
这里需要注意的是, 虽然是 int 类型, 但是它的值要用 双引号 围住.
删除数据(删除数据的一个属性):
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 err9 }
删除了 <0xfffd8d67d832b976> 这条数据的 属性, <0xfffd8d67d832b976> 是上面 name="Monkey" 的那条数据.
将数据的属性和关系都删除之后, 这条数据就相当于删除了.
直接根据 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 的坑中.
No comments:
Post a Comment