AppSync对接DynamoDB列表属性原子追加及其他列表操作实现咨询
核心结论
DynamoDB 原生支持列表的原子操作,包含类 splice 的按索引删除、插入、替换操作,所有操作均通过调整 AppSync Resolver 的更新表达式实现,是否修改 GraphQL Schema 和客户端代码取决于你是否要单独封装列表操作接口。
支持的列表操作类型
DynamoDB 内置的更新表达式可直接实现以下列表操作,所有操作均为原子性,不会出现并发修改冲突:
- 尾部追加元素:使用
list_append()函数实现 - 头部插入元素:把
list_append()的参数顺序调换即可 - 按索引替换元素:直接给
列表字段[索引]赋值 - 按索引删除元素:使用
REMOVE指令指定索引 - 类
splice操作:组合删除和插入逻辑即可实现「删除指定范围元素 + 插入新元素」的效果
具体实现步骤
1. 调整 GraphQL Schema(可选)
默认 Amplify 自动生成的 updateTable mutation 是全量覆盖逻辑,你可以选择复用现有 mutation,也可以新增专门的列表操作 mutation 更便于调用:
# 你原有TableType的定义不变,新增两个mutation即可 type Mutation { # 追加元素到objects列表 appendToObjects(id: ID!, newElement: ObjectItem!): TableType # 类splice操作:从startIndex开始删除deleteCount个元素,插入newElements spliceObjects(id: ID!, startIndex: Int!, deleteCount: Int!, newElements: [ObjectItem]): TableType }
2. 配置 AppSync Resolver 请求模板
找到对应 mutation 的 DynamoDB resolver,将请求模板改成使用更新表达式的形式即可,不需要改响应模板:
原子追加操作的请求模板示例:
{ "version": "2018-05-29", "operation": "UpdateItem", "key": { "id": $util.dynamodb.toDynamoDBJson($ctx.args.id) }, "update": { "expression": "SET #objects = list_append(#objects, :newElems)", "expressionNames": { "#objects": "objects" }, "expressionValues": { ":newElems": $util.dynamodb.toDynamoDBJson([$ctx.args.newElement]) } }, "returnValues": "ALL_NEW" }
类splice操作的请求模板示例:
#set($startIdx = $ctx.args.startIndex) { "version": "2018-05-29", "operation": "UpdateItem", "key": { "id": $util.dynamodb.toDynamoDBJson($ctx.args.id) }, #if($ctx.args.deleteCount > 0) "remove": { "expression": "REMOVE #objects[$startIdx]#foreach($i in [1..$ctx.args.deleteCount-1])#set($tempIdx = $startIdx + $i), #objects[$tempIdx]#end" }, #end #if($ctx.args.newElements && $ctx.args.newElements.size() > 0) "update": { "expression": "SET #objects = list_append(list_append(#objects[0:$startIdx], :newElems), #objects[$startIdx:])", "expressionNames": { "#objects": "objects" }, "expressionValues": { ":newElems": $util.dynamodb.toDynamoDBJson($ctx.args.newElements) } }, #end "returnValues": "ALL_NEW" }
3. 客户端调用调整
客户端调用逻辑和你原有写法一致,只需要替换 mutation 和传对应参数即可:
import { API } from "aws-amplify"; // 引入你新增的mutation import { appendToObjects, spliceObjects } from "../graphql/mutations"; // 追加元素调用示例 const addRes = await API.graphql({ query: appendToObjects, variables: { id: "something", newElement: { "testKey": "testVal", "start": 50, "end": 70 } } }) // splice操作调用示例:从索引2开始删除1个元素,插入2个新元素 const spliceRes = await API.graphql({ query: spliceObjects, variables: { id: "something", startIndex: 2, deleteCount: 1, newElements: [ { "foo": ["fifth"], "start": 40, "end": 60 }, { "bar": ["sixth"], "start": 60, "end": 80 } ] } })
注意事项
- DynamoDB 列表索引从0开始,索引超出实际长度时操作会静默失败,建议操作前先校验索引范围
- 同一个
UpdateItem请求内的所有操作都是原子性的,不会出现中间状态 - 如果你不想新增自定义 mutation,也可以直接修改原有
updateTable的 resolver 逻辑,加参数判断:当传入appendElements或spliceConfig等字段时走列表操作逻辑,否则走默认全量覆盖逻辑,不需要改 GraphQL Schema
内容的提问来源于stack exchange,提问作者Alien13
相关产品推荐
相关产品推荐

