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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30296850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 16:50:59  来源:igfitidea点击:

Is It possible to change value of Range key in DynamoDB Table?

javaamazon-dynamodb

提问by Geek_To_Learn

I know it may be a very silly question, but I am new to DynamoDB.

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

My doubt is is it possible to update the value of a Range Key in DynamoDB.

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

Suppose My Table is "TEST"

假设我的表是“TEST”

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

I want to modify DateAttribute.

我想修改Date属性。

Initial Values in Table was:

表中的初始值为:

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

Running this code below. I am able to change the NameAttribute which is GSI.

在下面运行此代码。我可以更改NameGSI的属性。

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

But When I change this line

但是当我改变这条线时

item1.put("Name", update);

with

 item1.put("Date", update);

I am getting some error as

我收到了一些错误

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)

So Is it possible to change the range Key value?

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

采纳答案by mkobit

No, like the exception message states, you Cannot update attribute Date. This attribute is part of the key.

不,就像异常消息所述,您Cannot update attribute Date. This attribute is part of the key.

You can also see this under the AttributeUpdatesdocumentation:

您还可以在AttributeUpdates文档下看到这一点:

The names of attributes to be modified, the action to perform on each, and the new value for each. If you are updating an attribute that is an index key attribute for any indexes on that table, the attribute type must match the index key type defined in the AttributesDefinition of the table description. You can use UpdateItem to update any nonkey attributes.

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

The documentation states that you can update any attribute for "an attribute that is an index key attribute for any indexes on that table", which means that when you update an attribute that is projected onto an index, even it is is part of that indexes key, that index will also be updated to reflect the original item.

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

回答by mbo

From the docs of AttributeValueUpdate

来自AttributeValueUpdate的文档

You cannot use UpdateItem to update any primary key attributes. Instead, you will need to delete the item, and then use PutItem to create a new item with new attributes.

您不能使用 UpdateItem 更新任何主键属性。相反,您需要删除该项目,然后使用 PutItem 创建具有新属性的新项目。

回答by Johnny Wu

It's a little buried but in docs for UpdateItemit says: "You can use UpdateItem to update any nonkey attributes."

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

So, currently the only way to update the primary key of an item is to delete the old item and write a new one.

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

回答by Rafi

Here is my implementation of updating id in .net by deleting the item and then recreating it with the new id. I assume java is very similar:

这是我通过删除项目然后使用新 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("************************************************");
    }
}

To call it just do this:

要调用它,只需执行以下操作:

UpdateId.ChangeId("OriginalId", "NewId");