Amplify + AppSync 不改变对象
Posted
技术标签:
【中文标题】Amplify + AppSync 不改变对象【英文标题】:Amplify + AppSync not mutating object 【发布时间】: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 个选项可供选择:createVideoOnDemand 和 listVideoOnDemand,我在那里没有看到更新,这可能表明存在问题?
【问题讨论】:
你能分享 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"
并且它不会更改描述字段。我可以设置新字段,但无法编辑现有字段。在这一点上我一无所知。
【参考方案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
【讨论】:
以上是关于Amplify + AppSync 不改变对象的主要内容,如果未能解决你的问题,请参考以下文章
AWS Amplify Appsync 在创建具有关系的对象时解决错误
aws amplify appsync 中的 Graphql 突变错误
将现有 AppSync API 与/ Amplify 一起使用
“没有当前用户”:是不是甚至可以通过 Amplify 使用身份验证类型 AMAZON_COGNITO_USER_POOLS 对 AWS AppSync 进行未经身份验证的调用?