私はそれが非常にばかげた質問であるかもしれないことを知っています、しかし私はDynamoDBに新しいです。
私の疑問は、DynamoDBの範囲キーの値を更新できることです。
私のテーブルが「テスト」だとしましょう
{
ID : PK/HK
Date : RK
Name : GSI
Add : LSI
}
Date
属性を変更したい。
テーブルの初期値は次のとおりです。
{
ID = "344"
Date = "5656"
Name = "ABC"
}
以下のこのコードを実行します。 GSIであるName
属性を変更できます。
Map<String,AttributeValue> item = new HashMap<String,AttributeValue>();
item.put("ID", new AttributeValue("344"));
item.put("Date", new AttributeValue("5656"));
Map<String,AttributeValueUpdate> item1 = new HashMap<String,AttributeValueUpdate>();
AttributeValueUpdate update = new AttributeValueUpdate().withValue(new AttributeValue("AMIT")).withAction("PUT");
item1.put("Name", update);
UpdateItemRequest updateItemreq = new UpdateItemRequest("Test",item,item1);
UpdateItemResult updateItemres = dynamoDBUSEast.updateItem(updateItemreq);
しかし、この行を変更すると
item1.put("Name", update);
と
item1.put("Date", update);
私はいくつかのエラーを得ています
Exception in thread "main" com.amazonaws.AmazonServiceException: One or more parameter values were invalid: Cannot update attribute Date. This attribute is part of the key (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: HRRP24Q7C48AMD8ASAI992L6MBVV4KQNSO5AEMVJF66Q9ASUAAJG)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.Java:820)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.Java:439)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.Java:245)
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.Java:2908)
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.updateItem(AmazonDynamoDBClient.Java:1256)
それで、範囲キーの値を変更することは可能ですか?
いいえ、例外メッセージの状態と同様に、あなたはCannot update attribute Date. This attribute is part of the key
。
AttributeUpdates
documentation でも確認できます。
変更する属性の名前、それぞれに対して実行するアクション、およびそれぞれの新しい値。そのテーブルのインデックスのインデックスキー属性である属性を更新する場合、属性タイプはテーブルの説明のAttributesDefinitionで定義されているインデックスキータイプと一致する必要があります。 UpdateItemを使用して、非キー属性を更新できます。
ドキュメントには、「そのテーブル上の任意のインデックスのインデックスキー属性である属性」の任意の属性を更新できると記載されています。つまり、インデックスに投影されている属性を更新すると、それがそのインデックスの一部であっても更新されますキー、そのインデックスも元のアイテムを反映するように更新されます。
AttributeValueUpdate のドキュメントから
UpdateItemを使用して主キー属性を更新することはできません。代わりに、アイテムを削除し、PutItemを使用して新しい属性で新しいアイテムを作成する必要があります。
少し埋もれていますが、ドキュメントの pdateItem には、「UpdateItemを使用して、非キー属性を更新できます」と記載されています。
したがって、現在、アイテムの主キーを更新する唯一の方法は、古いアイテムを削除して新しいアイテムを書き込むことです。
これは、アイテムを削除して新しいIDで再作成することにより、.netでIDを更新する私の実装です。 Javaは非常に似ていると思います:
// Based on https://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetItemsExample.html
public class UpdateId
{
private static string tableName = "MyTableName";
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();
private static bool isVerbose = false;
public static void ChangeId(string currentId, string newId)
{
try
{
var deletedItem = DeleteItem(currentId);
if (deletedItem.Count == 0)
{
Console.WriteLine($"ERROR: Item to delete not found: {currentId}");
return;
}
deletedItem["Id"] = new AttributeValue
{
S = newId
};
CreateItem(deletedItem);
var updatedItem = RetrieveItem(newId);
if (updatedItem.Count > 0 && updatedItem["Id"].S == newId)
{
Console.WriteLine($"Item id successfully changed from ({currentId}) to ({newId})");
}
else
{
Console.WriteLine($"ERROR: Item id didn't change from ({currentId}) to ({newId})");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("To continue, press Enter");
Console.ReadLine();
}
}
private static void CreateItem(Dictionary<string, AttributeValue> item)
{
var request = new PutItemRequest
{
TableName = tableName,
Item = item
};
client.PutItem(request);
}
private static Dictionary<string, AttributeValue> RetrieveItem(string id)
{
var request = new GetItemRequest
{
TableName = tableName,
Key = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
S = id
} }
},
ConsistentRead = true
};
var response = client.GetItem(request);
// Check the response.
var attributeList = response.Item; // attribute list in the response.
if (isVerbose)
{
Console.WriteLine("\nPrinting item after retrieving it ............");
PrintItem(attributeList);
}
return attributeList;
}
private static Dictionary<string, AttributeValue> DeleteItem(string id)
{
var request = new DeleteItemRequest
{
TableName = tableName,
Key = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
S = id
} }
},
// Return the entire item as it appeared before the update.
ReturnValues = "ALL_OLD",
// ExpressionAttributeNames = new Dictionary<string, string>()
// {
// {"#IP", "InPublication"}
// },
// ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
// {
// {":inpub",new AttributeValue {
// BOOL = false
// }}
// },
// ConditionExpression = "#IP = :inpub"
};
var response = client.DeleteItem(request);
// Check the response.
var attributeList = response.Attributes; // Attribute list in the response.
// Print item.
if (isVerbose)
{
Console.WriteLine("\nPrinting item that was just deleted ............");
PrintItem(attributeList);
}
return attributeList;
}
private static void PrintItem(Dictionary<string, AttributeValue> attributeList)
{
foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
{
string attributeName = kvp.Key;
AttributeValue value = kvp.Value;
Console.WriteLine(
attributeName + " " +
(value.S == null ? "" : "S=[" + value.S + "]") +
(value.N == null ? "" : "N=[" + value.N + "]") +
(value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray()) + "]") +
(value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray()) + "]")
);
}
Console.WriteLine("************************************************");
}
}
呼び出すには、次のようにします。
UpdateId.ChangeId("OriginalId", "NewId");