dynamoDBの条件付き書き込みで、オブジェクト内の特定要素に対して制約を付ける方法をメモする
dynamoDBのConditionExpressionについて
dynamoDBのあるレコードを更新する場合に下記のように条件をつけることができる
- レコードに特定キーが存在する場合のみput
- レコードの特定キー値がある値の場合のみput
例:productTable
{
name:"apple", // hash key
price: 300,
isBought: false
}
実行コード(lambda)
const AWS = require('aws-sdk');
const dynamoDB = new AWS.DynamoDB.DocumentClient();
exports.handler = async(event, context) => {
const params = {
TableName: "productTable",
Key:{
name: "apple"
},
ExpressionAttributeNames: {
'#isBought': 'isBought'
},
ExpressionAttributeValues: {
':isBought': true,
':expectIsBought': false
},
UpdateExpression: 'SET #isBought = :isBought',
ConditionExpression: '#isBought = :expectIsBought' // まだ購入されていない商品である場合のみ更新する
};
const data = await dynamoDB.update(params).promise();
}
ConditionExpressionの条件をオブジェクトの1要素にしたい場合
例:productTable
{
name:"apple", // hash key
price: 300,
info: {
reservation: "Aさん",
isBought: false
}
}
実行コード(lambda)
const AWS = require('aws-sdk');
const dynamoDB = new AWS.DynamoDB.DocumentClient();
exports.handler = async(event, context) => {
const params = {
TableName: "productTable",
Key:{
name: "apple"
},
ExpressionAttributeNames: {
'#info': 'info'
'#reservation': 'reservation'
'#isBought': 'isBought'
},
ExpressionAttributeValues: {
':isBought': true,
':expectReservation': 'Aさん'
':expectIsBought': false
},
UpdateExpression: 'SET #info.#isBought = :isBought',
ConditionExpression: '#info.#reservation = :expectReservation AND #info.#isBought = :expectIsBought' // Aさんが予約し、まだ購入されていない商品である場合のみ更新する
};
const data = await dynamoDB.update(params).promise();
}
オブジェクトの要素参照は#key1.#key2
のような形で参照できる
ConditionExpressionの条件を配列の1要素にしたい場合
例:productTable
{
name:"apple", // hash key
price: 300,
stocks: [true, false]
}
実行コード(lambda)
const AWS = require('aws-sdk');
const dynamoDB = new AWS.DynamoDB.DocumentClient();
exports.handler = async(event, context) => {
const index = 1
const params = {
TableName: "productTable",
Key:{
name: "apple"
},
ExpressionAttributeNames: {
'#stocks': 'stocks'
},
ExpressionAttributeValues: {
':isBought': true,
':expectIsBought': false
},
UpdateExpression: `SET #stocks[${index}] = :isBought`, //
ConditionExpression: `#stocks[${index}]= :expectIsBought` // 指定した配列番号のストックがまだ購入されていない場合のみ更新する
};
const data = await dynamoDB.update(params).promise();
}
配列要素は#key1[1]
のように参照できる。conditionExpressionは文字列型なので、配列番号は文字列への埋め込みが必要
ConditionExpressionの条件を配列内オブジェクトの1要素にしたい場合
例:productTable
{
name:"apple", // hash key
price: 300,
stocks: [
{reservation: 'Aさん', isBought: true},
{reservation: 'Bさん', isBought: false}
]
}
実行コード(lambda)
const AWS = require('aws-sdk');
const dynamoDB = new AWS.DynamoDB.DocumentClient();
exports.handler = async(event, context) => {
const index = 1
const reservation = 'Bさん'
const params = {
TableName: "productTable",
Key:{
name: "apple"
},
ExpressionAttributeNames: {
'#stocks': 'stocks',
'#isBought': 'isBought',
'#reservation': 'reservation'
},
ExpressionAttributeValues: {
':isBought': true,
':expectIsBought': false,
':expectReservation': reservation
},
UpdateExpression: `SET #stocks[${index}].#isBought = :isBought`,
ConditionExpression: `#stocks[${index}].#isBought = :expectIsBought AND #stocks[${index}].#reservation = :expectReservation` // 指定した配列番号のストックがまだ購入されていない場合かつBさん予約の商品である場合のみ更新する
};
const data = await dynamoDB.update(params).promise();
}