如何在AWS AppSync的GraphQL中PUT/关联用户与Record嵌套数据?
嘿,刚上手AppSync搭GraphQL后端处理一对多关联是吧?我来给你一步步讲清楚怎么实现你要的功能:
一、创建关联到用户的Record的Mutation语法
你通过「Create Resources」生成的DynamoDB表和自动解析器,应该已经帮你生成了CreateRecord的mutation,而且因为你的Records类型里有userId: ID!,所以这个mutation的输入参数里肯定包含userId。直接用下面的语法就能创建关联到指定用户的Record:
mutation CreateUserRecord { createRecord(input: { userId: "要关联的用户ID", // 替换成实际存在的用户ID title: "我的第一条记录", // 这里填Records类型的其他必填字段 }) { id userId title } }
要是你发现自动生成的CreateRecordInput里没userId,那大概率是创建Resources的时候没把userId设为外键关联,不过按照你的Schema来看,应该不会出现这种情况,实在不行你可以手动给CreateRecordInput加上这个字段。
二、创建用户时同时写入关联的Record数据
默认情况下,AppSync自动生成的CreateUser mutation只负责写入Users表,不会处理子对象Records的创建。要实现“创建用户同时加部分Record”,得做两个关键调整:
1. 扩展CreateUser的输入类型
首先得修改你的GraphQL Schema,给CreateUserInput加个records字段,用来接收要同时创建的Record列表:
input CreateUserInput { name: String! records: [CreateRecordInput!] # 新增这个字段,用来传要创建的Record数据 }
放心,你原来的User类型里的records字段,AppSync应该已经自动生成了关联查询的解析器,后续查用户的时候能直接拉到对应的Records。
2. 调整CreateUser的解析器逻辑
默认的CreateUser解析器只写Users表,得改它让它写完用户后,批量把Records也写到对应的表里。这里有两种常用方法:
方法一:用Pipeline Resolver(更推荐,逻辑拆分清晰)
Pipeline Resolver可以把多个操作串起来:先创建User,再批量创建Records。
- 第一步:新建一个Function,直接复用原来CreateUser的解析器逻辑,负责创建用户
- 第二步:再建一个Function,复用CreateRecord的逻辑,循环处理输入的records列表,批量创建
- 第三步:把这两个Function拼成一个Pipeline Resolver,绑定到
CreateUsermutation上就行
方法二:直接修改VTL模板(快速实现)
要是不想搞Pipeline,也可以直接改CreateUser的VTL模板,在写入用户后调用DynamoDB的批量写入接口。给你个参考模板:
#set($userInput = $ctx.args.input) # 自动生成用户ID #set($userId = $util.autoId()) # 构造要写入Users表的用户数据 #set($userItem = { "id": $userId, "name": $util.dynamodb.toDynamoDB($userInput.name) }) # 先把用户写入DynamoDB $util.qr($ctx.stash.put("user", $userItem)) $util.qr($ctx.stash.put("userId", $userId)) # 如果输入里有records,就批量写入Records表 #if($userInput.records) #set($recordItems = []) #foreach($record in $userInput.records) # 构造单个Record的DynamoDB格式数据 #set($recordItem = { "id": $util.autoId(), "userId": $util.dynamodb.toDynamoDB($userId), "title": $util.dynamodb.toDynamoDB($record.title) # 这里记得加上Records的其他必填字段 }) $util.qr($recordItems.add($recordItem)) #end # 调用批量写入接口 #set($batchRequest = { "requestItems": { "Records": { "putRequest": $recordItems } } }) $util.qr($ctx.stash.put("batchResult", $util.dynamodb.batchPutItem($batchRequest))) #end # 返回创建好的用户,顺便把传入的Records数据也返回(如果需要的话) { "id": $userId, "name": $userInput.name, "records": $userInput.records }
3. 用修改后的Mutation创建用户和Records
调整完之后,就可以用下面的mutation一次性创建用户和关联的Records了:
mutation CreateUserWithRecords { createUser(input: { name: "张三", records: [ { title: "日常记录1" # 其他Records字段 }, { title: "日常记录2" # 其他Records字段 } ] }) { id name records { id title } } }
几个小提醒
- 确保Records表的
userId字段有GSI(全局二级索引),AppSync自动创建表的时候应该会帮你加,这样查询用户的records时才会高效 - 如果要保证“用户和Records要么都创建成功,要么都失败”,可以用AppSync的事务解析器,调用DynamoDB的
TransactWriteItemsAPI - 后续查询用户的时候,直接用
user查询就能拉到关联的records列表,自动生成的解析器已经帮你处理了关联逻辑
内容的提问来源于stack exchange,提问作者rm.rf.etc

