【问题标题】:Amplify + AppSync not mutating objectAmplify + AppSync 不改变对象
【发布时间】:2020-01-07 16:45:32
【问题描述】:

我试图在没有任何先验知识的情况下使用 Amplify + AppSync/GraphQL 设置应用程序,但现在我面临很多问题,以至于我怀疑这是一个好的决定。

我已经通过 Amplify 添加了一个 AppSync API

查询目前工作正常,但是,我很难使突变工作,更糟糕的是,它们没有给我任何错误。

我的数据库架构的重要部分如下:

type Mutation {
    updateVideoOnDemand(input: UpdateVideoOnDemandInput!): VideoOnDemand
}

type ScriptRow {
    loop: Int
    timeStart: Int
    character: String
    text: String
    guessed: Boolean
}

input ScriptRowInput {
    loop: Int
    timeStart: Int
    character: String
    text: String
    guessed: Boolean
}

input UpdateVideoOnDemandInput {
    guid: String!
    thumbNailUrl: [String]
    startTime: String
    workflowStatus: String
    srcVideo: String
    hlsUrl: String
    dashUrl: String
    scriptUrl: String
    mp4Urls: [String]
    transcriptUri: String
    isLoadingLoops: Boolean
    documentKey: String
    initialOffset: Int
    videoOffset: Int
    scriptRows: [ScriptRowInput!]
}

type VideoOnDemand {
    guid: String!
    thumbNailUrl: [String]
    startTime: String
    workflowStatus: String
    srcVideo: String
    hlsUrl: String
    dashUrl: String
    scriptUrl: String
    mp4Urls: [String]
    transcriptUri: String
    isLoadingLoops: Boolean
    documentKey: String
    initialOffset: Int
    videoOffset: Int
    scriptRows: [ScriptRow]
}

然后,我使用 Amplify codegen 工具生成了本地代码 哪个看起来不错

export const updateVideoOnDemand = `mutation UpdateVideoOnDemand($input: UpdateVideoOnDemandInput!) {
  updateVideoOnDemand(input: $input) {
    guid
    thumbNailUrl
    startTime
    workflowStatus
    srcVideo
    hlsUrl
    dashUrl
    scriptUrl
    mp4Urls
    transcriptUri
    isLoadingLoops
    documentKey
    initialOffset
    videoOffset
    scriptRows {
      loop
      timeStart
      character
      text
      guessed
    }
  }
}
`;

首先我尝试使用简单的 AWS API.GraphQL

        API.graphql(graphqlOperation(mutations.updateVideoOnDemand, {
          input: {
            guid: video.guid,
            initialOffset: values.initial_offset,
            videoOffset: values.video_offset,
            workflowStatus: 'Test',
            isLoadingLoops: true,
            scriptRows: rows,
          }
        })).then(
          updatedVideo => {
            message.success('Saved');
          }
        ).catch(err => message.error('Error saving data: ' + err))

突变的映射解析器:

{
  "version": "2017-02-28",
  "operation": "UpdateItem",
  "key": {
    "guid": $util.dynamodb.toDynamoDBJson($ctx.args.input.guid),
  },

  ## Set up some space to keep track of things we're updating **
  #set( $expNames  = {} )
  #set( $expValues = {} )
  #set( $expSet = {} )
  #set( $expAdd = {} )
  #set( $expRemove = [] )

  ## Iterate through each argument, skipping keys **
  #foreach( $entry in $util.map.copyAndRemoveAllKeys($ctx.args.input, ["guid"]).entrySet() )
    #if( $util.isNull($entry.value) )
      ## If the argument is set to "null", then remove that attribute from the item in DynamoDB **

      #set( $discard = ${expRemove.add("#${entry.key}")} )
      $!{expNames.put("#${entry.key}", "${entry.key}")}
    #else
      ## Otherwise set (or update) the attribute on the item in DynamoDB **

      $!{expSet.put("#${entry.key}", ":${entry.key}")}
      $!{expNames.put("#${entry.key}", "${entry.key}")}
      $!{expValues.put(":${entry.key}", $util.dynamodb.toDynamoDB($entry.value))}
    #end
  #end

  ## Start building the update expression, starting with attributes we're going to SET **
  #set( $expression = "" )
  #if( !${expSet.isEmpty()} )
    #set( $expression = "SET" )
    #foreach( $entry in $expSet.entrySet() )
      #set( $expression = "${expression} ${entry.key} = ${entry.value}" )
      #if ( $foreach.hasNext )
        #set( $expression = "${expression}," )
      #end
    #end
  #end

  ## Continue building the update expression, adding attributes we're going to ADD **
  #if( !${expAdd.isEmpty()} )
    #set( $expression = "${expression} ADD" )
    #foreach( $entry in $expAdd.entrySet() )
      #set( $expression = "${expression} ${entry.key} ${entry.value}" )
      #if ( $foreach.hasNext )
        #set( $expression = "${expression}," )
      #end
    #end
  #end

  ## Continue building the update expression, adding attributes we're going to REMOVE **
  #if( !${expRemove.isEmpty()} )
    #set( $expression = "${expression} REMOVE" )

    #foreach( $entry in $expRemove )
      #set( $expression = "${expression} ${entry}" )
      #if ( $foreach.hasNext )
        #set( $expression = "${expression}," )
      #end
    #end
  #end

  ## Finally, write the update expression into the document, along with any expressionNames and expressionValues **
  "update": {
    "expression": "${expression}",
    #if( !${expNames.isEmpty()} )
      "expressionNames": $utils.toJson($expNames),
    #end
    #if( !${expValues.isEmpty()} )
      "expressionValues": $utils.toJson($expValues),
    #end
  },

  "condition": {
    "expression": "attribute_exists(#guid)",
    "expressionNames": {
      "#guid": "guid",
    },
  }
}

响应映射模板:

$util.toJson($context.result)

该命令似乎运行成功,我得到了更新的视频,我可以看到更新的数据......但是数据库端的某些字段没有更新......在这种情况下,字段@ 987654326@ 和 scriptRows 没有更新......如果我重新加载页面,我会再次获得旧结果,如果我直接检查 DynamoDB 实例,我还会看到前 3 个项目已更新,但其余部分没有更新。

我已尝试迁移代码以使用 AWSAppSync Client/Apollo.... 错误仍然存​​在。

知道是什么原因造成的吗?

更新

有一件事我不确定它们是否可能表明有问题:

当我转到 AppSync 控制台 -> 查询,然后单击“播放”图标时,我只看到 2 个选项可供选择:createVideoOnDemandlistVideoOnDemand,我在那里没有看到更新,这可能表明存在问题?

【问题讨论】:

  • 你能分享 API 上那个突变的映射模板吗?
  • ``` ``` 变异帮助 { updateVideoOnDemand(input: { guid: "2", initialOffset: 1, videoOffset:2, workflowStatus: "Test", isLoadingLoops: true, scriptRows: [{ loop: 1 timeStart: 2 character: "test" text: "test" 猜测: false }]}) { guid isLoadingLoops initialOffset videoOffset workflowStatus scriptRows { loop timeStart character text } } ```
  • @danielfranca 更新突变是否显示在控制台的文档部分?单击“播放”图标时显示的选项取决于您在控制台编辑器中编写的查询,因此这不一定表明存在问题。但是,如果文档部分中没有它,则意味着您尚未将最新的架构 + 解析器推送到云端。如果您想将您的放大项目发布到 GitHub,我可以帮助您进一步排除故障,并在我们解决此问题后返回此处。
  • 在这种情况下,有一个 DynamoDB 触发器正在覆盖表上的更改。
  • 我遇到了这个。在无法从 Lambda 或 Angular 更新后,我通过 AppSync 直接触发了突变。 updateAsset(input: {id: "b34d3aa3-fbc4-48b5-acba-af616001630f", description: "AppSync"} 并且它不会更改描述字段。我可以设置新字段,但无法编辑现有字段。在这一点上我一无所知。

标签: graphql apollo react-apollo aws-amplify aws-appsync


【解决方案1】:

看起来这与应用同步/放大解决冲突的方式有关。如果启用了 DataStore,则冲突解决处于活动状态。

当您在服务器端使用来自 NodeJS 的 GraphQL 以及在客户端使用 DataStore 客户端(例如带有 IAM 身份验证的 lambda)时,您可能需要此信息:https://docs.amplify.aws/lib/graphqlapi/graphql-from-nodejs/q/platform/js

包括 _version 数字有效。有道理。

另请参阅: https://github.com/aws-amplify/amplify-cli/issues/3237(更新突变 GraphQL 以使新创建的模型不起作用),请参阅评论:https://github.com/aws-amplify/amplify-cli/issues/3237#issuecomment-584375936

无效示例:

工作示例:

请注意:

https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js#writing-data-from-the-appsync-console

从 AppSync 控制台写入数据

DataStore 主要是为开发人员设计的,无需专注于 后端并让您的应用程序代码和工作流程创建 一切。但是,在某些用例中,您将使用 AppSync 控制台、Lambda 函数或其他带外进程 写入数据(例如批处理操作或数据迁移),您可能 在没有 DataStore 客户端的情况下发送 GraphQL 操作。

在这些情况下,重要的是 GraphQL 的选择集 突变包括模型的所有必需字段,包括: _lastChangedAt、_version 和 _deleted,以便 DataStore 客户端可以对这些更新做出反应。您还需要发送当前 变异输入参数中的对象版本为 _version 以便 服务可以相应地采取行动。如果您不发送此信息 在全局同步过程中,客户端最终仍会赶上, 但您不会看到客户端 DataStore 的实时更新 存储库。

突变示例:

mutation UpdatePost {
  updatePost(input: {
    id: "12345"
    title: "updated title 19:40"
    status: ACTIVE
    rating: 5
    _version: 7
  }) {
    id
    title
    status
    rating
    _lastChangedAt
    _version
    _deleted
  }
}

【讨论】:

    猜你喜欢
    • 2018-10-27
    • 1970-01-01
    • 2020-11-23
    • 2021-04-24
    • 2022-10-31
    • 2020-02-03
    • 2019-10-19
    • 2021-04-15
    • 2021-06-23
    相关资源
    最近更新 更多