web-dev-qa-db-fra.com

Comment empêcher un élément DynamoDB d'être écrasé si une entrée existe déjà

Im essayant d'écrire une fonction lambda pour ajouter de nouvelles données à une table DynamoDB. De la lecture des documents à:

http://docs.aws.Amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#put-property La méthode PUT: "Crée un nouvel élément ou remplace un ancien élément par un nouvel élément en déléguant à AWS.DynamoDB.putItem (). "

Autre que de vérifier un objet avant de "mettre", y a-t-il un paramètre ou un indicateur d'échec de l'objet existe lorsque le PUT est tenté?

Je peux voir dans

params -> Expected -> Exists (Bool)

mais je ne vois aucune documentation sur ce que cela fait.

Quelle serait la meilleure architecture (ou à jeun) pour empêcher l'écrasement d'un élément?

Query the table first and if no item exists then add the item

ou

Attempt to insert the item and on failure because of duplicate entry report this back? (Is there a way to prevent item overwrite?)
16
Mathew Jenkinson

ConditionExpression peut être utilisé pour vérifier si les valeurs d'attribut de clé existent déjà dans la table et effectuer l'opération PUT uniquement si les valeurs de clé ne sont pas présentes dans la table.

Lorsque vous exécutez le code ci-dessous, la première fois que l'opération put doit réussir. Lors de la deuxième exécution, l'opération put doit échouer avec une exception "Échec de la demande conditionnelle".

Ma table de films possède à la fois des clés de partition et de tri. J'ai donc utilisé les deux attributs dans l'expression conditionnelle.

Exemple de code avec put conditionnel: -

var table = "Movies";

var year = 1502;
var title = "The Big New Movie";

var params = {
    TableName:table,
    Item:{
        "yearkey": year,
        "title": title,
        "info":{
            "plot": "Nothing happens at all.",
            "rating": 0
        }
    },
    ConditionExpression: "yearkey <> :yearKeyVal AND #title <>  :title",
    ExpressionAttributeNames: { 
        "#title" : "title" 
     },
    ExpressionAttributeValues: {
        ":yearKeyVal" : year,
        ":title": {"S": title}
    }
};

console.log("Adding a new item...");
docClient.put(params, function(err, data) {
    if (err) {
        console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
    } else {        
        console.log("Added item:", JSON.stringify(data, null, 2));
    }
});

Exception lorsque l'opération de put est exécutée une deuxième fois: -

Unable to add item. Error JSON: {
  "message": "The conditional request failed",
  "code": "ConditionalCheckFailedException",
  "time": "2017-10-02T18:26:26.093Z",
  "requestId": "7ae3b0c4-3872-478d-908c-94bc9492a43a",
  "statusCode": 400,
  "retryable": false,
  "retryDelay": 0
}
16
notionquest

Je vois que cette question concerne le langage JavaScript, de toute façon j'écrirai aussi pour Java (peut-être cela sera utile pour quelqu'un):

DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression();
Map<String, ExpectedAttributeValue> expectedAttributes =
        ImmutableMapParameter.<String, ExpectedAttributeValue>builder()
                .put("hashKeyAttrName", new ExpectedAttributeValue(false))
                .put("rangeKeyAttrName", new ExpectedAttributeValue(false))
                .build();
saveExpression.setExpected(expectedAttributes);
saveExpression.setConditionalOperator(ConditionalOperator.AND);

try {
    dynamoDBMapper.save(item, saveExpression);
} catch (ConditionalCheckFailedException e) {
    e.printStackTrace();
}

ConditionalCheckFailedException sera jeté au cas où nous essaierions d'enregistrer l'élément avec une paire de clés de hachage et de plage de clés déjà existante dans DynamoDB.

5