我尝试使用 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)
该命令似乎运行成功,我得到了更新的视频作为结果,并且我可以看到其上更新的数据...但是某些字段未在数据库端更新...在本例中字段 isLoadingLoops
和 scriptRows
未更新...如果我重新加载页面,我会再次得到旧结果,如果我直接检查 DynamoDB 实例,我还会看到前 3 个项目已更新,但其余部分未更新。
我已尝试迁移代码以使用 AWSAppSync Client/Apollo...但错误仍然存在。
知道是什么原因造成的吗?
更新
有一件事我不确定它们是否可能表明出现了问题:
当我转到 AppSync 控制台 -> 查询,然后单击“播放”图标时,我只看到 2 个选项可供选择:createVideoOnDemand 和 listVideoOnDemand,我在那里没有看到更新,这可能表明存在问题?
最佳答案
看起来这与应用程序同步/放大解决冲突的方式有关。如果启用了 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
请注意:
Writing data from the AppSync console
DataStore is designed primarily for developers to not have to focus on the backend and let your application code and workflow create everything. However, there will be some use cases where you will use the AppSync console, a Lambda function, or other out of band processes to write data (such as batch actions or data migrations) and you might send GraphQL operations without the DataStore client.
In these cases it’s important that the selection set of your GraphQL mutation includes all the required fields of the model, including: _lastChangedAt, _version, and _deleted so that the DataStore clients can react to these updates. You will also need to send the current object version in the mutation input argument as _version so that the service can act accordingly. If you do not send this information the clients will still eventually catch up during the global sync process, but you will not see realtime updates to the client DataStore repositories.
突变示例:
mutation UpdatePost {
updatePost(input: {
id: "12345"
title: "updated title 19:40"
status: ACTIVE
rating: 5
_version: 7
}) {
id
title
status
rating
_lastChangedAt
_version
_deleted
}
}
关于graphql - Amplify + AppSync 不会改变对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57794338/