使用NodeJS发送基于DynamoDb流的graphQL突变

时间:2019-03-13 21:01:35

标签: node.js amazon-web-services aws-lambda amazon-dynamodb graphql

当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函数,就像我说的那样,它仅与RekognitionId一起使用,格式为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);
        });

    });
};

4 个答案:

答案 0 :(得分:1)

我已经多次(可悲!)看到此错误,并且措辞不佳,因为它没有提及映射我们可能认为的方式。错误是您的graphql连接字符串格式错误或缺少关键数据。

有两种解决方案。首先是在某种类型的沙箱中试用graphql,AWS Amplify和Apollo都将它们放在控制台中。对于AWS,您还可以模拟数据库并从计算机上运行它-尽管您需要在模拟环境中创建一些数据-如果在本地计算机上作为两组数据进行开发,则在进行下一步操作之前将其清除-真实与模拟交织在一起!是的,在那一个上浪费了几个小时!

另一种解决方案是简单地调出数据字符串,无论您在查询中依赖什么数据以确保数据存在。偶尔看起来都很不错,但是当数据丢失时,往往会发生该错误。

您可以测试数据。获取一个好的数据字符串,然后故意取所需的!元素或其他元素,您将在某个时候得到映射错误。这是指graphql无法映射数据,而不是map的javascript含义。

答案 1 :(得分:1)

本周我遇到了同样的错误,并且花费了大量的时间。对我来说,原因只是检查我作为GraphQL突变变量传入的内容。首先,我传递了一个数字而不是一个对象(即,我在for for in in循环时偶然传递了键),其次,我对突变的输入变量执行了JSON.stringify。这些一起造成了很多头挠。以防万一其他人遇到此错误,请在此处添加它。检查您输入的内容!

答案 2 :(得分:0)

这是一个 VTL 模板错误。如果没有看到模板很难说,但是“Map”和“String”绝对是 VTL 类型,看起来像某个地方将字符串值分配给输入对象,而实际上它应该是类型 map 的值。可能是 json 字符串没有转换成地图。

答案 3 :(得分:0)

我在实现中遇到了完全相同的错误。

我的原因是我的 UpdateFaceInput 没有与我的 UpdateFace 类型相同的内部结构。

因此,如果有人出现此错误,只是想提示您查看 type updateFaceinput updateFaceInput 定义也可能是一个不错的尝试。