前面介绍的GraphQL都是在自己的服务器上运行的。下面介绍一下如何在AWS AppSync中使用GraphQL,并分别以DynamoDB及Lambda作为数据源。
GraphQL系列教程:
- GraphQL的设计理念及安装配置
- Schema的基本使用
- GraphQL中的类型及类型间的关系
- 使用MongoDB作为数据存储层
- 在React中使用GraphQL
- 在AWS AppSync中使用GraphQL
- 如何在serverless中定义GraphQL API-不使用AppSync
- 如何在serverless中定义GraphQL API-使用AppSync并使用Lambda作为数据源
AWS AppSync介绍
先来看看官网这个架构图:

Source:AWS AppSync
AppSync的作用就是为应用程序提供一个统一的接口,可以进行各种查询和操作。它可以用来连接SQL, NoSQL, OpenSearch, HTTP/REST, Lambda等不同的数据源。和自己搭建的服务器相比,在AppSync中可以方便的使用其他AWS服务,比如Cognito,IAM,API Key等等。
在AppSync中又两个重要的概念:
- Data Source数据源: 数据源可以是持久层的数据存储(SQL / NoSQL),也可以是其他的Lambda函数,或者HTTP API。
- Resolver:这点和普通GraphQL中的resolver一样,用于定义获取/操作数据的逻辑。
同时需要注意的是,在AppSync中有一个比较重要的概念:Subscription(订阅)。也就是说,当进行数据操作的时候,可以自动触发一切其他的行为,比如Lambda。其最终的定义类似于这样:

创建AppSync API(DynamoDB版)
在控制台中创建API
进入AWS AppSync控制台,选择:
- Create API
- Build from scratch, 单击”Start”
- 输入App的名字,比如“AWS AppSync tutorial”后单击“Create”
定义Schema,Resolvers
单击“Edit Schema”之后单击“Create Resources”。这里还以前面用到的StudentType为例。需要注意的是,和前面定义的Schema不同,这里用的类型:
type Student {
id: ID!
name: String!
address: String!
}
其余的都选择默认设置:

然后单击”Create”就会创建这个Schema以及配套的DynamoDB table。创建完毕后会返回Schema页面,可以看到queries和mutations都已经创建好了:

同时还有配套的Resolvers:

单击一个resolver,比如createStudent:
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($util.autoId()),
},
"attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
"condition": {
"expression": "attribute_not_exists(#id)",
"expressionNames": {
"#id": "id",
},
},
}
可以看到它首先检测id是否存在:
"expression": "attribute_not_exists(#id)"
然后才进行插入操作:
"operation": "PutItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($util.autoId()),
},
"attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
而Response mapping则定义了返回用户的数据格式,这里默认值代表使用DyanomoDB的返回值,意味着新建的Student:
$util.toJson($context.result)
测试Query API
单击屏幕左边的Queries,然后输入以下的Query:
mutation newStudent{
createStudent(input: {name:"Jack", address:"101 Fake Street"}) {
id
name
address
}
}
可以看到其返回值为:
{
"data": {
"createStudent": {
"id": "a5bcc986-4539-4331-9723-6065d883f0ee",
"name": "Jack",
"address": "101 Fake Street"
}
}
}
这个操作也可以再左边的小窗口中操作:

再进行一下查询,这个操作完全类似于GraphQL Web UI:

创建AppSync API(Lambda版)
创建一个Lambda
为了简单,这里直接在AWS Console中创建一个Lambda:
exports.handler = async (event) => {
let students = [
{ id: '1', name: 'Lucas', address: '1 Fake Street'},
{ id: '2', name: 'Paul', address: '2 Fake Street'},
{ id: '3', name: 'Jess', address: '3 Fake Street'},
{ id: '4', name: 'Tom', address: '4 Fake Street'},
{ id: '5', name: 'Ned', address: '5 Fake Street'},
{ id: '6', name: 'Dan', address: '6 Fake Street'},
{ id: '7', name: 'Luke', address: '7 Fake Street'},
{ id: '8', name: 'Lucy', address: '8 Fake Street'},
{ id: '9', name: 'Chole', address: '9 Fake Street'},
{ id: '10', name: 'Amy', address: '10 Fake Street'}
]
switch(event.field) {
case 'getStudent':
let {id} = event.arguments;
return students.filter(s => s.id === id)[0]
default:
return "Student not found."
}
};
在AppSync中创建数据源
回到刚才的AppSync API,然后注册一个新的data source:

首先删除getStudent resolver到StudentTable的绑定:

Request mapping template:
{
"version" : "2017-02-28",
"operation": "Invoke",
"payload": {
"field": "getStudent",
"arguments": $utils.toJson($context.arguments)
}
}
Response mapping template (系统默认值):
$util.toJson($context.result)

测试
下面进行查询,可以看到,getStudent的数据源已经是Lambda,而不是DynamoDB了:
