DynamoDB putItem ConditionExpression无法匹配event.identityId

时间:2017-11-10 19:24:49

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

我正在AWS Lambda函数中使用以下node.js代码,以便在Cognito sync事件中从另一个名为StoryEntity的表中的源数据中插入或更新名为Submissions的DynamoDB表中的记录通过在名为“batch”的属性中存储新值来触发此函数。除了putItem调用上的ConditionExpression之外,一切似乎都在工作。如果StoryEntity中的记录不存在,一切都很好,但如果它们已经存在,我会在日志输出中报告错误,如:

  

2017-11-10T19:08:55.685Z 98e60436-c64a-11e7-9a2a-dfba66e9157a错误   插入:ConditionalCheckFailedException:条件请求   失败

     

2017-11-10T19:08:55.705Z 98e60436-c64a-11e7-9a2a-dfba66e9157a错误   插入:ConditionalCheckFailedException:条件请求   失败

uid列中的值类似于us-east-2:11476ace-a944-4769-89cb-c5ad8e84b8a9。只要我以相同的身份登录,它就不会改变,我就是这样。我不明白为什么它不会使用该条件表达式更新现有记录。 (它是在我介绍ConditionExpression之前做的。)

'use strict';

console.log('Loading function');

var doc = require('dynamodb-doc');
var dynamodb = new doc.DynamoDB();

exports.handler = (event, context, callback) => {
    var batch = event.datasetRecords.batch.newValue;
    var datetime = new Date().getTime();
    function doPut(err, data) {
        if (err) {
            console.log('Error inserting: ' + err);
            callback(`Error putting item into DB: ${err}.`);
        }}
    function doDelete(err, data) {
        if (err) {
            console.log('Error deleting: ' + err);
            callback(`Error deleting item: ${err}.`);
        }}
    function doQuery(err, data) {
        if (err) {
            console.log("Error querying: " + err);
            callback(`Error querying submission: ${err}`);
        } else {
            data.Items.forEach(function(item) {
                Object.assign(item, {
                   "uid" : event.identityId,
                   "date": datetime
                });
                dynamodb.putItem({"TableName" : "StoryEntity",
                   "Item" : item,
                    "ConditionExpression" :
                        "attribute_not_exists(#u) or #u=:user",
                    "ExpressionAttributeNames" : {"#u" : "uid"},
                    "ExpressionAttributeValues" :
                        {":user":{"S":event.identityId}}
                }, doPut);
                dynamodb.deleteItem({"TableName" : "Submission",
                    "Key" : {"Batch" : batch,
                    "EntityId": item.EntityId}
                }, doDelete);
            });
        }
    }
    dynamodb.query({ TableName: "Submission",
        ProjectionExpression: "EntityId, #t, EntityType, #n, Container, Destination, Target",
        KeyConditionExpression: "#b = :batch",
        ExpressionAttributeNames: {
            "#b" : "Batch",
            "#t" : "Text",
            "#n" : "Name"
        },
        ExpressionAttributeValues: {
            ":batch": batch
        }
    }, doQuery);
    callback(null, event);
};

1 个答案:

答案 0 :(得分:1)

我仍然不清楚为什么我之前尝试实现此解决方案的尝试不成功,但显然问题与:user的值格式有关。关于这个的文档是令人沮丧的不一致(我找不到任何与我必须使用的语法相匹配的文档 - 消除类型说明符键),并且错误消息令人沮丧地模糊,但在修改代码以纠正之后一些异步排序问题,我通过尝试在我的表达式中使用<运算符而不是=来获取更有用的错误消息。在比较类型<的值时,这会产生一条消息,说明M如何不是有效的运算符。显然,在这种情况下,我需要 not 在我的值规范中包含指定字符"S"的类型,因为这会导致框架将整个值解释为map,隐式插入{ {1}}键将值类型指定为映射。我在上面的代码中尝试了这一点,但仍然出现了错误,因此必须要求其他一些与此相关的更改才能使其正常工作。以下是最终代码。

"M"