使用 NodeJS 发送基于 DynamoDb 流的 graphQL 突变
Posted
技术标签:
【中文标题】使用 NodeJS 发送基于 DynamoDb 流的 graphQL 突变【英文标题】:Send graphQL mutation based on DynamoDb stream with NodeJS 【发布时间】:2019-08-04 16:12:41 【问题描述】:我正在尝试在 DynamoDb 表收到新行时更新 GraphQL 订阅。我得到以下代码仅使用 RekognitionId,但我没有尝试发送整个 NewImage 对象,我无法使其工作。我遇到了各种各样的类型问题,但没有真正的信息来解决它。最能说明问题的是:
"Error: GraphQL error: Variable 'input' has an invalid value. Expected type 'Map' but was 'String'. Variables for input objects must be an instance of type 'Map'."
很遗憾,我找不到对名为“map”的 GraphQL 类型的单个引用,所以它可能是乱码。
有人有这方面的经验吗?这是我的 Lambda 函数,就像我说它只使用格式化为 dynamoDb semi-json-string "S": "id"
global.WebSocket = require('ws');
require('es6-promise').polyfill();
require('isomorphic-fetch');
const AWS = require('aws-sdk');
const aws_exports = require('./aws-exports').default;
const AWSAppSyncClient = require('aws-appsync').default;
exports.handler = async (event, context, callback) =>
if(!event.Records.length)
console.log('no records');
return false;
const AUTH_TYPE = require('aws-appsync/lib/link/auth-link').AUTH_TYPE;
const url = aws_exports.ENDPOINT;
const region = aws_exports.REGION;
const type = AUTH_TYPE.AMAZON_COGNITO_USER_POOLS;
AWS.config.update(
region: aws_exports.REGION,
credentials: new AWS.Credentials(
accessKeyId: aws_exports.AWS_ACCESS_KEY_ID,
secretAccessKey: aws_exports.AWS_SECRET_ACCESS_KEY
)
);
const cognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider( apiVersion: '2016-04-18' );
const initiateAuth = async ( clientId, username, password ) => cognitoIdentityServiceProvider.initiateAuth(
AuthFlow: 'USER_PASSWORD_AUTH',
ClientId: clientId,
AuthParameters:
USERNAME: username,
PASSWORD: password,
,
).promise();
const AuthenticationResult = await initiateAuth(
clientId: '*******',
username: '*******',
password: '*******',
);
const accessToken = AuthenticationResult && AuthenticationResult.AccessToken;
// Import gql helper and craft a GraphQL query
const gql = require('graphql-tag');
const query = gql(`
mutation faceAdded($input: UpdateFaceInput!)
updateFace(input: $input)
RekognitionId
Emotions
Confidence
Type
AgeRange
Beard
Mustache
Gender
Eyeglasses
`);
// Set up Apollo client
const client = new AWSAppSyncClient(
url: url,
region: region,
auth:
type: type,
jwtToken: accessToken,
,
disableOffline: true //Uncomment for AWS Lambda
);
return runMutationInClient(client, query, event.Records[0], (res) =>
return res;
);
const runMutationInClient = async (client, query, RekognitionObj, callback) =>
await client.hydrated().then( async (client) =>
console.log('Running mutation in Lambda: ', query, 'RekognitionId: ', RekognitionObj);
var inputObj = AWS.DynamoDB.Converter.unmarshall(RekognitionObj.dynamodb.NewImage)
await client.mutate(
mutation: query,
variables:
input:
RekognitionId: "S": inputObj.RekognitionId,
Emotion: "L": []
,
fetchPolicy: 'no-cache'
).then(function logData(data)
console.log('LAMBDA results of query: ', data);
callback(data);
)
.catch((error)=>
console.log('LAMBDA ERROR:', error);
callback(error);
);
);
;
【问题讨论】:
看起来更像是 VTL 模板错误。你确定突变有效吗?您是否尝试手动执行突变? @Trilliput 错误来自 VTL 模板,但这些错误是由 AWS appsync 自动生成并在 appsync 控制台中工作的。 欢迎接受我的回答。 【参考方案1】:我经常看到这个错误(很遗憾!),它的措辞很糟糕,因为它没有提到映射我们可能思考的方式。错误是您的 graphql 连接字符串格式错误或缺少关键数据。
有两种解决方案。首先是在某种沙箱中试用 graphql,AWS Amplify 和 Apollo 都将它们放在控制台中。在 AWS 的情况下,您还可以模拟您的数据库并从您的机器上运行它 - 尽管您需要在模拟环境中创建一些数据 - 如果您在本地机器上作为两组数据进行开发,请在继续之前将其清除- 真实和模拟交织在一起!是的,在那上面浪费了几个小时!
另一种解决方案是简单地排除数据字符串,无论您在查询中依赖什么数据来确保数据存在。有时看起来一切都很好,但当数据丢失时往往会发生该错误。
您可以测试数据。得到一个好的数据字符串然后故意取需要的! element out 或另一个,你会在某个时候得到映射错误。这是指graphql无法映射数据,而不是map的javascript含义。
【讨论】:
这听起来像是解决方案,但您能否提供一些关于格式错误的数据是什么样子以及应该是什么样子的详细信息? 我当时正在处理的响应正如 OP 所提到的那样。我无法提供更多信息,因为这是很久以前的事了。【参考方案2】:这周我也犯了同样的错误,而且有很多时间。我的原因只是检查我作为变量传递给我的 GraphQL 突变的内容。首先,我传递的是一个数字而不是一个对象(即,我在循环中执行 for x 时意外传递了密钥),其次,我正在为我的突变对输入变量执行 JSON.stringify。这些一起引起了很多头疼。在此处添加它以防其他人遇到此错误。检查您传递的内容!
【讨论】:
卡在同样的问题上......现在迷路了。【参考方案3】:这是一个 VTL 模板错误。没有看到模板很难说,但“Map”和“String”绝对是 VTL 类型,看起来像是在某个地方为输入对象分配了一个字符串值,而它应该是 map 类型的值。可能一个 json 字符串没有被转换成地图。
【讨论】:
【参考方案4】:在我的实现中,我遇到了完全相同的错误。
我的原因是我的UpdateFaceInput
的内部结构与我的UpdateFace
类型不同。
因此,如果有人遇到此错误,只是想提示您查看type updateFace
和input updateFaceInput
定义可能也是一个不错的尝试。
【讨论】:
【参考方案5】:如果您尝试根据条件进行查询或变异,则需要使用here 中的一些条件子句。例如,您的代码应如下所示:
await client.mutate(
mutation: query,
variables:
input:
RekognitionId: eq: inputObj.RekognitionId,
Emotion: eq: []
,
fetchPolicy: 'no-cache'
).then(function logData(data)
console.log('LAMBDA results of query: ', data);
callback(data);
)
.catch((error)=>
console.log('LAMBDA ERROR:', error);
callback(error);
);
在我看来,“地图”错误有点愚蠢,它并没有给你太多的工作空间。此错误也可能与其他问题有关,但似乎大多数这些问题都与条件有关。
【讨论】:
以上是关于使用 NodeJS 发送基于 DynamoDb 流的 graphQL 突变的主要内容,如果未能解决你的问题,请参考以下文章
使用 AWS Java DynamoDB 流 Kinesis 适配器处理 DynamoDB 流
Python Lambda 函数解析 DynamoDB 的 JSON 格式
使用 NodeJS 将新对象附加到 DynamoDB 中的 JSON 数组