我们会比较简单的 GraphQL 实现和纯 REST 替代方案,在一种普通场景(呈现博客文章页面)下对比它们的实现复杂性和效率。 -- Alexandru Topliceanu
本文导航
-摘要 …… 00%
-介绍 …… 03%
-相关阅读 …… 11%
-在 GraphQL 中建模一个博客引擎 …… 12%
-设计 PostgreSQL 数据库 …… 37%
-Golang API 实现 …… 44%
-普通场景下和 REST 的对比 …… 60%
-总结 …… 84%
-附录1:图数据库和高效数据存储 …… 88%
编译自: http://alexandrutopliceanu.ro/post/graphql-with-go-and-postgresql
作者: Alexandru Topliceanu
译者: ictlyh
type User {
id: ID
email: String!
post(id: ID!): Post
posts: [Post!]!
follower(id: ID!): User
followers: [User!]!
followee(id: ID!): User
followees: [User!]!
}
type Post {
id: ID
user: User!
title: String!
body: String!
comment(id: ID!): Comment
comments: [Comment!]!
}
type Comment {
id: ID
user: User!
post: Post!
title: String
body: String!
}
type Query {
user(id: ID!): User
}
type Mutation {
createUser(email: String!): User
removeUser(id: ID!): Boolean
follow(follower: ID!, followee: ID!): Boolean
unfollow(follower: ID!, followee: ID!): Boolean
createPost(user: ID!, title: String!, body: String!): Post
removePost(id: ID!): Boolean
createComment(user: ID!, post: ID!, title: String!, body: String!): Comment
removeComment(id: ID!): Boolean
}
# 创建用户 1、2 和 3 的更改。更改和查询类似,在该情景中我们检索新创建用户的 id 和 email。
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user1@x.co"){id, email}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user2@x.co"){id, email}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user3@x.co"){id, email}}'
# 为用户添加博文的更改。为了和模式匹配我们需要检索他们的 id,否则会出现错误。
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:1,title:"post1",body:"body1"){id}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:1,title:"post2",body:"body2"){id}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:2,title:"post3",body:"body3"){id}}'
# 博文所有评论的更改。`createComment` 需要用户 id,标题和正文。看列表 1 的模式。
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:2,post:1,title:"comment1",body:"comment1"){id}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:1,post:3,title:"comment2",body:"comment2"){id}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:3,post:3,title:"comment3",body:"comment3"){id}}'
# 让用户 3 关注用户 1 和用户 2 的更改。注意 `follow` 更改只返回一个布尔值而不需要指定。
curl -XPOST http://vm:8080/graphql -d 'mutation {follow(follower:3, followee:1)}'
curl -XPOST http://vm:8080/graphql -d 'mutation {follow(follower:3, followee:2)}'
# 用户获取用户 1 所有数据的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:1)}'
# 用户获取用户 2 和用户 1 的关注者的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:2){followers{id, email}}}'
curl -XPOST http://vm:8080/graphql -d '{user(id:1){followers{id, email}}}'
# 检测用户 2 是否被用户 1 关注的查询。如果是,检索用户 1 的 email,否则返回空。
curl -XPOST http://vm:8080/graphql -d '{user(id:2){follower(id:1){email}}}'
# 返回用户 3 关注的所有用户 id 和 email 的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:3){followees{id, email}}}'
# 如果用户 3 被用户 1 关注,就获取用户 3 email 的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:1){followee(id:3){email}}}'
# 获取用户 1 的第二篇博文的查询,检索它的标题和正文。如果博文 2 不是由用户 1 创建的,就会返回空。
curl -XPOST http://vm:8080/graphql -d '{user(id:1){post(id:2){title,body}}}'
# 获取用户 1 的所有博文的所有数据的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:1){posts{id,title,body}}}'
# 获取写博文 2 用户的查询,如果博文 2 是由 用户 1 撰写;一个现实语言灵活性的例证。
curl -XPOST http://vm:8080/graphql -d '{user(id:1){post(id:2){user{id,email}}}}'
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
email VARCHAR(100) NOT NULL
);
CREATE TABLE IF NOT EXISTS posts (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
title VARCHAR(200) NOT NULL,
body TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS comments (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
title VARCHAR(200) NOT NULL,
body TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS followers (
follower_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
followee_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
PRIMARY KEY(follower_id, followee_id)
);
var CommentType = graphql.NewObject(graphql.ObjectConfig{
Name: "Comment",
Fields: graphql.Fields{
"id": &graphql.Field{
Type: graphql.NewNonNull(graphql.ID),
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if comment, ok := p.Source.(*Comment); ok == true {
return comment.ID, nil
}
return nil, nil
},
},
"title": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if comment, ok := p.Source.(*Comment); ok == true {
return comment.Title, nil
}
return nil, nil
},
},
"body": &graphql.Field{
Type: graphql.NewNonNull(graphql.ID),
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if comment, ok := p.Source.(*Comment); ok == true {
return comment.Body, nil
}
return nil, nil
},
},
},
})
func init() {
CommentType.AddFieldConfig("user", &graphql.Field{
Type: UserType,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if comment, ok := p.Source.(*Comment); ok == true {
return GetUserByID(comment.UserID)
}
return nil, nil
},
})
CommentType.AddFieldConfig("post", &graphql.Field{
Type: PostType,
Args: graphql.FieldConfigArgument{
"id": &graphql.ArgumentConfig{
Description: "Post ID",
Type: graphql.NewNonNull(graphql.ID),
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
i := p.Args["id"].(string)
id, err := strconv.Atoi(i)
if err != nil {
return nil, err
}
return GetPostByID(id)
},
})
}
+------+ +------+ +--------+
|client| |server| |database|
+--+---+ +--+---+ +----+---+
| GET /blogs/:id | |
1. +-------------------------> SELECT * FROM blogs... |
| +--------------------------->
|
| | |
| GET /users/:id | |
2. +-------------------------> SELECT * FROM users... |
| +--------------------------->
|
| | |
| GET /blogs/:id/comments | |
3. +-------------------------> SELECT * FROM comments... |
| +--------------------------->
|
| | |
| GET /users/:id/followers| |
4. +-------------------------> SELECT * FROM followers.. |
| +--------------------------->
|
| | |
+ + +
+------+ +------+ +--------+
|client| |server| |database|
+--+---+ +--+---+ +----+---+
| GET /graphql | |
1. +-------------------------> SELECT * FROM blogs... |
| +--------------------------->
|
| | |
| | |
| | |
2. | | SELECT * FROM users... |
| +--------------------------->
|
| | |
| | |
| | |
3. | | SELECT * FROM comments... |
| +--------------------------->
|
| | |
| | |
| | |
4. | | SELECT * FROM followers.. |
| +--------------------------->
|
| | |
+ + +
{
user(id: 1) {
followers
post(id: 1) {
title
body
comments {
id
title
user {
id
}
}
}
}
}
参与评论
手机查看
返回顶部