是否可以在DynamoDB表中更改Range键的值?

时间:2015-05-18 06:57:05

标签: java amazon-dynamodb

我知道这可能是一个非常愚蠢的问题,但我是DynamoDB的新手。

我怀疑是否可以在DynamoDB中更新范围键的值。

假设我的表是" TEST"

{
ID : PK/HK
Date : RK
Name : GSI 
Add : LSI
}

我想修改Date属性。

表中的初始值为:

{
ID = "344"
Date = "5656"
Name = "ABC"
}

在下面运行此代码。我可以更改Name属性,即GSI。

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)

那么是否可以更改范围键值?

4 个答案:

答案 0 :(得分:11)

不,与异常消息一样,您Cannot update attribute Date. This attribute is part of the key

您还可以在AttributeUpdates documentation

下看到这一点
  

要修改的属性的名称,要对每个属性执行的操作,   以及每个人的新价值。如果要更新属性   该表上任何索引的索引键属性,即该属性   type必须与AttributesDefinition中定义的索引键类型匹配   表的描述。 您可以使用UpdateItem更新任何非密钥   属性

该文档指出,您可以更新&#34;属性作为该表&#34;上任何索引的索引键属性的任何属性,这意味着当您更新投影到索引上的属性时,即使它是索引键的一部分,该索引也将更新以反映原始项目。

答案 1 :(得分:9)

来自AttributeValueUpdate

的文档
  

您无法使用UpdateItem更新任何主键属性。   相反,您需要删除该项,然后使用PutItem   使用新属性创建一个新项目。

答案 2 :(得分:3)

它有点被埋没但在UpdateItem的文档中它说: “您可以使用UpdateItem更新任何非键属性。”

因此,目前更新项目主键的唯一方法是删除旧项目并写一个新项目。

答案 3 :(得分:0)

这是我在.net中更新ID的实现,方法是删除该项目,然后使用新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");