• サンプルコードは Node 8.10, Python 3.7
  • 属性名が予約語とかぶってるせい。
  • ExpressionAttributeNames を使って、式の中の属性名もプレースホルダにする必要がある。

属性名に『Status』ってつけたら、予約語とかぶっちゃってたらしくて、条件付きUpdateしようとした時に Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: (属性名) って言われた。

じゃあ予約語は属性名に使えないのかと言うとそんなことはなくて、UpdateExpression 上では当該の属性名をプレースホルダにしておき、ExpressionAttributeNames で属性名を指定してやればいいらしい。

なお ExpressionAttributeNames 自体はupdate特有のものではなくて、クエリでも同じように使うみたいなので留意。

↓のコードは、MyTable の Id = 999 の項目について、Status = 1 ならば Status = 2 に更新する条件付きUpdate。

Node.js
'use strict';

const aws = require('aws-sdk');
const docClient = new aws.DynamoDB.DocumentClient({	
	region: 'ap-northeast-1',
});

docClient.update({
	TableName: 'MyTable',
	Key: {
		'Id': 999,
	},
	UpdateExpression: 'set #st = :newst',
	ConditionExpression: '#st = :oldst',
	ExpressionAttributeNames: {
		'#st': 'Status'  // ←属性名をプレースホルダにする。名前には井桁 (#) をつける。
	},
	ExpressionAttributeValues: {
		':newst': 2,
		':oldst': 1,
	},
	ReturnValues: 'UPDATED_NEW'
}, function(err, data) {
	if (err) {
		console.error('エラー', err);
	} else {
		console.log('更新成功', data);
	}
});

↓Pythonでもほぼ同じ。

import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('MyTable')

try:
	res = table.update_item(
		Key={
			'Id': 999,
		},
		UpdateExpression='set #st = :newst',
		ConditionExpression='#st = :oldst',
		ExpressionAttributeNames= {
			'#st': 'Status'
		},
		ExpressionAttributeValues={
			':newst': 2,
			':oldst': 1,
		},
		ReturnValues='UPDATED_NEW'
	)
	print('更新成功', res)
except Exception as e:
	print('エラー', e)