DynamoDB putItem ConditionExpression andernfalls match event.identityId

Ich bin mit dem folgenden node.js code, der in einer AWS Lambda-Funktion zum einfügen oder aktualisieren von Datensätzen in einer DynamoDB-Tabelle genannt StoryEntity von Quell-Daten in einer anderen Tabelle namens Submissions wenn ein Cognito-sync-Ereignis löst in dieser Funktion durch die Speicherung eines neuen Wertes in eine Eigenschaft namens „batch“. Alles scheint zu funktionieren außer dem ConditionExpression auf der putItem nennen. Wenn die Datensätze noch nicht vorhanden sind in StoryEntity ist alles in Ordnung, aber wenn Sie schon vorhanden sind, bekomme ich Fehler in der log-Ausgabe:

2017-11-10T19:08:55.685 Z 98e60436-c64a-11e7-9a2a-dfba66e9157a Fehler
einfügen: ConditionalCheckFailedException: Die bedingte Anforderung
fehlgeschlagen

2017-11-10T19:08:55.705 Z 98e60436-c64a-11e7-9a2a-dfba66e9157a Fehler
einfügen: ConditionalCheckFailedException: Die bedingte Anforderung
fehlgeschlagen

Den Wert der uid-Spalte sieht aus wie us-east-2:11476ace-a944-4769-89cb-c5ad8e84b8a9. Es ändert sich nicht, so lange ich eingeloggt bin mit der gleichen Identität, das ich bin. Ich verstehe nicht, warum es nicht aktualisieren bestehender Datensätze mit dieser bedingte Ausdruck im Ort. (Es Tat, bevor ich eingeführt 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);
};
InformationsquelleAutor BlueMonkMN | 2017-11-10



One Reply
  1. 2

    Ich bin mir immer noch nicht klar, warum meine bisherigen versuche zur Umsetzung dieser Lösung waren erfolglos, aber offenbar war das problem im Zusammenhang mit der format der Wert für :user. Die Dokumentation dieser ist frustrierend inkonsistent (ich finde keine Dokumentation entspricht der syntax, die ich benutzen musste, um diese Arbeit zu machen – Wegfall der Typ-Bezeichner, Schlüssel), und die Fehlermeldungen sind frustrierend vage, aber nach den code zu ändern, zu korrigieren einige asynchrone Sequenzierung Probleme, ich war in der Lage, eine hilfreiche Fehlermeldung, indem Sie versuchen, verwenden Sie die < Betreiber in meinem Ausdruck statt =. Dies ergab eine Nachricht darüber, wie < ist kein Gültiger operator beim vergleichen der Werte des Typs M. So scheint, in diesem Kontext, muss ich nicht gehören die Art der Angabe von Zeichen "S" in meine Wert-Spezifikation, da das bewirkt, dass der Rahmen zu interpretieren, der ganze Wert als eine Karte, implizit einlegen der "M" Schlüssel angeben den Wert geben als eine Karte. Ich hatte versucht, dass in dem obigen code, aber immer noch ein Fehler, so manche andere änderung, kombiniert mit dieser gewesen sein muss, die erforderlich sind, um diese arbeiten. Unten ist der endgültige code.

    '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();
        var putList = [];
    
        function putError(err) {
            console.log('Error inserting: ' + err);
            throw `Error putting item into DB: ${err}.`;
        }
        function doDelete(err, data) {
            if (err) {
                console.log('Error deleting: ' + err);
                throw `Error deleting item: ${err}.`;
            }}
        function doQuery(err, data) {
            if (err) {
                console.log("Error querying: " + err);
                throw `Error querying submission: ${err}`;
            } else {
                data.Items.forEach(function(item) {
                    Object.assign(item, {
                       "uid" : event.identityId,
                       "date": datetime
                    });
                    var putRequest = {"TableName" : "StoryEntity",
                       "Item" : item,
                        "ConditionExpression" :
                            "attribute_not_exists(#u) or (#u=:user)",
                        "ExpressionAttributeNames" : {"#u":"uid"},
                        "ExpressionAttributeValues" : {":user":event.identityId}
                    };
                    var promise = dynamodb.putItem(putRequest).promise();
                    putList.push({"promise":promise, "entityId":item.EntityId});
                });
                var promiseList = [];
                putList.forEach(function(item){
                    promiseList.push(item.promise.then(function() {
                        dynamodb.deleteItem({"TableName" : "Submission",
                            "Key" : {"Batch" : batch,
                                "EntityId": item.entityId
                            }}, doDelete);
                    }, putError));
                });
                Promise.all(promiseList).then(function() {
                    console.log("Success!");
                    callback(null, event);
                }, function(err) {
                    console.log(err);
                    callback(err);
                });
            }
        }
        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);
    };
    • Ist das nicht die ConditionExpression sollen, werfen diese exception aus, wenn das Element schon vorhanden ist? Ich denke, es muss das beabsichtigte Verhalten. Oder bin ich hier etwas fehlt?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.