Amplify GraphQL更新数组字段时追加而非替换的无Datastore场景解决方案
问题原因
Amplify GraphQL API 对非@model修饰的自定义嵌套类型数组,默认更新策略为追加,该逻辑与是否开启Datastore、冲突解决无关。
适配方案
按优先级从高到低选择即可:
方案1:修改Schema指定更新策略(最简便,无需改业务代码)
给SomeObject的media字段添加@updateStrategy指令,显式指定更新时直接替换数组:
type SomeObject @model @auth( rules: [ { allow: owner, operations: [create, delete, update] } ] ) { id: ID! version: Int! owner: String name: String media: [Media] @updateStrategy(strategy: REPLACE) # 新增这行指令 } type Media { id: ID! owner: String mediaType: String! order: Int! createdAt: String updatedAt: String }
修改后执行amplify push更新云端配置,重新生成客户端代码后,原有Amplify.API.mutate的update调用就会直接替换media数组,不会再追加。
方案2:手动构造自定义GraphQL请求
如果不方便修改Schema,可以直接自定义mutation语句绕过默认更新策略:
// 要替换的目标media数组 let newMediaList: [Media] = <#你的全新media数组#> // 自定义mutation语句 let updateMutation = """ mutation UpdateSomeObject($id: ID!, $version: Int!, $media: [MediaInput!]!) { updateSomeObject(input: { id: $id, version: $version, media: $media }) { id version name media { id mediaType order createdAt updatedAt } } } """ // 构造请求 let request = GraphQLRequest( document: updateMutation, variables: [ "id": <#目标SomeObject的ID#>, "version": <#当前最新的version值#>, "media": newMediaList.map { // 转成MediaInput结构,自动生成的代码会自带该类型 MediaInput( id: $0.id, owner: $0.owner, mediaType: $0.mediaType, order: $0.order, createdAt: $0.createdAt, updatedAt: $0.updatedAt ) } ], responseType: SomeObject.self, decodePath: "updateSomeObject" ) // 发起更新请求 Amplify.API.mutate(request: request) { result in switch result { case .success(let updatedObj): print("更新成功,media长度:\(updatedObj.media?.count ?? 0)") case .failure(let error): print("更新失败:\(error)") } }
注意事项
- 每次调用update接口必须传入当前最新的
version字段值,否则会触发版本校验失败,该校验是@model指令自带的能力,与冲突解决开关无关。 - 可通过打印
request的document和variables字段,校验实际发起请求的参数是否符合预期。
内容的提问来源于stack exchange,提问作者alionthego
相关产品推荐
相关产品推荐

