aws(学习笔记第四十八课) appsync-graphql-dynamodb
- 使用
graphql
来方便操作dynamodb
- 理解
graphql
中的graphql api
,schema
,resolver
学习内容:
graphql
graphql api
schema
resolver
1. 代码连接和修改
1.1 代码链接
代码链接(appsync-graphql-dynamodb)
1.2 代码修改
1.2.1 加上必要的depencies
各个resolver
创建的时候,都是需要data_source
的,所以需要事前将resolver
的depencies
加上data source
。
get_one_resolver.add_depends_on(data_source)
get_all_resolver.add_depends_on(data_source)
save_resolver.add_depends_on(data_source)
delete_resolver.add_depends_on(data_source)
1.2.2 加上必要的outputs
CfnOutput(
self, "AppSyncApiUrl",
value=items_graphql_api.attr_graph_ql_url,
description="AppSync GraphQL API URL"
)
CfnOutput(
self, "AppSyncApiKey",
value=items_api_key.attr_api_key, # 假设已定义 items_api_key = CfnApiKey(...)
description="AppSync API Key"
)
2. 整体架构
- 定义一个
graphql api
- 为了安全访问,定义一个
api key
- 定义一个
api schema
- 两个查询
api
,all
和get one
- 定义两个更新
api
,delete
和save
- 两个查询
- 定义了一个
dynamo table
,用来存储数据 - 对
schema
定义了四个resolver
all resovler
get one resolver
save resolver
delete resolver
3. 代码详细
3.1 定义api
以及api key
table_name = 'items'
items_graphql_api = CfnGraphQLApi(
self, 'ItemsApi',
name='items-api',
authentication_type='API_KEY'
)
items_api_key = CfnApiKey(
self, 'ItemsApiKey',
api_id=items_graphql_api.attr_api_id
)
3.2 定义api
的schema
api_schema = CfnGraphQLSchema(
self, 'ItemsSchema',
api_id=items_graphql_api.attr_api_id,
definition=f"""\
type {table_name} {{
{table_name}Id: ID!
name: String
}}
type Paginated{table_name} {{
items: [{table_name}!]!
nextToken: String
}}
type Query {{
all(limit: Int, nextToken: String): Paginated{table_name}!
getOne({table_name}Id: ID!): {table_name}
}}
type Mutation {{
save(name: String!): {table_name}
delete({table_name}Id: ID!): {table_name}
}}
type Schema {{
query: Query
mutation: Mutation
}}"""
)
3.3 定义dynamoDB table
items_table = Table(
self, 'ItemsTable',
table_name=table_name,
partition_key=Attribute(
name=f'{table_name}Id',
type=AttributeType.STRING
),
billing_mode=BillingMode.PAY_PER_REQUEST,
stream=StreamViewType.NEW_IMAGE,
# The default removal policy is RETAIN, which means that cdk
# destroy will not attempt to delete the new table, and it will
# remain in your account until manually deleted. By setting the
# policy to DESTROY, cdk destroy will delete the table (even if it
# has data in it)
removal_policy=RemovalPolicy.DESTROY # NOT recommended for production code
)
3.4 定义dynamoDB
访问的role
,以及data source
这里data source
,可以看出是将graphql api
和dynamoDB
的table
进行关联。
items_table_role = Role(
self, 'ItemsDynamoDBRole',
assumed_by=ServicePrincipal('appsync.amazonaws.com')
)
items_table_role.add_managed_policy(
ManagedPolicy.from_aws_managed_policy_name(
'AmazonDynamoDBFullAccess'
)
)
data_source = CfnDataSource(
self, 'ItemsDataSource',
api_id=items_graphql_api.attr_api_id,
name='ItemsDynamoDataSource',
type='AMAZON_DYNAMODB',
dynamo_db_config=CfnDataSource.DynamoDBConfigProperty(
table_name=items_table.table_name,
aws_region=self.region
),
service_role_arn=items_table_role.role_arn
)
3.5 定义四个api resolver
3.5.1 get one resolver
get_one_resolver = CfnResolver(
self, 'GetOneQueryResolver',
api_id=items_graphql_api.attr_api_id,
type_name='Query',
field_name='getOne',
data_source_name=data_source.name,
request_mapping_template=f"""\
{{
"version": "2017-02-28",
"operation": "GetItem",
"key": {{
"{table_name}Id": $util.dynamodb.toDynamoDBJson($ctx.args.{table_name}Id)
}}
}}""",
response_mapping_template="$util.toJson($ctx.result)"
)
get_one_resolver.add_depends_on(api_schema)
get_one_resolver.add_depends_on(data_source)
3.5.2 all resolver
get_all_resolver = CfnResolver(
self, 'GetAllQueryResolver',
api_id=items_graphql_api.attr_api_id,
type_name='Query',
field_name='all',
data_source_name=data_source.name,
request_mapping_template=f"""\
{{
"version": "2017-02-28",
"operation": "Scan",
"limit": $util.defaultIfNull($ctx.args.limit, 20),
"nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.nextToken, null))
}}""",
response_mapping_template="$util.toJson($ctx.result)"
)
get_all_resolver.add_depends_on(api_schema)
get_all_resolver.add_depends_on(data_source)
3.5.3 save resolver
save_resolver = CfnResolver(
self, 'SaveMutationResolver',
api_id=items_graphql_api.attr_api_id,
type_name='Mutation',
field_name='save',
data_source_name=data_source.name,
request_mapping_template=f"""\
{{
"version": "2017-02-28",
"operation": "PutItem",
"key": {{
"{table_name}Id": {{ "S": "$util.autoId()" }}
}},
"attributeValues": {{
"name": $util.dynamodb.toDynamoDBJson($ctx.args.name)
}}
}}""",
response_mapping_template="$util.toJson($ctx.result)"
)
save_resolver.add_depends_on(api_schema)
save_resolver.add_depends_on(data_source)
3.5.4 delete resolver
delete_resolver = CfnResolver(
self, 'DeleteMutationResolver',
api_id=items_graphql_api.attr_api_id,
type_name='Mutation',
field_name='delete',
data_source_name=data_source.name,
request_mapping_template=f"""\
{{
"version": "2017-02-28",
"operation": "DeleteItem",
"key": {{
"{table_name}Id": $util.dynamodb.toDynamoDBJson($ctx.args.{table_name}Id)
}}
}}""",
response_mapping_template="$util.toJson($ctx.result)"
)
delete_resolver.add_depends_on(api_schema)
delete_resolver.add_depends_on(data_source)
3.5.5 增加outputs
为了能够得到graphql api
的endpoint url
,还有访问api key
,这里进行outputs
的输出
CfnOutput(
self, "AppSyncApiUrl",
value=items_graphql_api.attr_graph_ql_url,
description="AppSync GraphQL API URL"
)
CfnOutput(
self, "AppSyncApiKey",
value=items_api_key.attr_api_key, # 假设已定义 items_api_key = CfnApiKey(...)
description="AppSync API Key"
)
4. 执行stack
4.1 执行stack
python -m venv ./venv
source .venv/Scripts/activate
pip install -r requirements.txt
cdk --require-approval never deploy
4.2 使用postman
进行api
调用,更新和查询dynamoDB table
4.2.1 生成GraphQL Request
4.2.2 使用save
进行数据做成
在authorization
的tab
上进行api key
的设定。
指定完毕,可以看到生成的数据中,已经生成了itemsID
。