web-dev-qa-db-ja.com

エントリが既に存在する場合にDynamoDBアイテムが上書きされないようにする方法

新しいデータをDynamoDBテーブルに追加するラムダ関数を記述しようとしています。以下のドキュメントを読むことから:

http://docs.aws.Amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#put-property PUTメソッド:「新しいアイテムを作成するか、古いアイテムをAWS.DynamoDB.putItem()に委任することで新しいアイテム。

「プット」する前にオブジェクトのチェックを行う以外に、PUTが試行されたときにオブジェクトを失敗させる設定またはフラグが存在しますか?

私は見ることができます

params -> Expected -> Exists (Bool)

しかし、これが何をするかについてのドキュメントを見ることができません。

アイテムの上書きを防ぐための最良のアーキテクチャ(または断食)は何ですか?

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

または

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

ConditionExpressionを使用して、キー属性値がテーブルにすでに存在するかどうかを確認し、キー値がテーブルに存在しない場合にのみPUT操作を実行できます。

以下のコードを実行すると、最初にput操作が成功するはずです。 2回目の実行では、put操作は"Conditional request failed"例外で失敗するはずです。

私の映画テーブルには、パーティションキーとソートキーの両方があります。したがって、私は条件式で両方の属性を使用しました。

条件付きのサンプルコード:-

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));
    }
});

2回目にput操作が実行された場合の例外:-

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

この質問はJavaScript言語に関連しているようですが、とにかくJavaについても記述します(たぶん誰かに役立つでしょう):

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は、hashKeyとrangeKeyの既存のペアがDynamoDBに既に存在するアイテムを保存しようとした場合にスローされます。

5