简体   繁体   中英

How can I update a nested field in DynamoDB?

I defined a DynamoDB table and it has a nested field site . I'd like to update the field site.enable in below code. But when I run the update command I got this error:

ValidationException: The document path provided in the update expression is invalid for update`

What should I do in order to fix the issue?

{
      TableName: 'MyTable',
      Key: {
        id: '4b7020d2-2d19-4aeb-7f27e49d5bec',
        type: '80422149-c97d-4a1a-7bf20ef57056',
      },
      UpdateExpression: 'set #site.#siteenable= :siteenable',
      ExpressionAttributeValues: {
        ':siteenable': true,
      },
      ExpressionAttributeNames: {
        '#siteenable': 'enable',
        '#site': 'site',
      }
    }

You don't mention a programming language, so I'm going to assume what I'm used to: Python.

In Python there are two ways you can do this:

  1. The lower level client API, which requires you to format the data the way DynamoDB would
def enable_site_with_client():

    ddb = boto3.client("dynamodb")
    ddb.update_item(
        TableName=TABLE_NAME,
        Key={
            "PK": {"S": "SITE_ENTRY"}
        },
        UpdateExpression="SET #site.#enabled = :update_value",
        ExpressionAttributeNames={
            "#site": "site",
            "#enabled": "enabled"
        },
        ExpressionAttributeValues={
            ":update_value": {"BOOL": True}
        }
    )
  1. The higher level resource API, which allows you to use the language native data structures
def enable_site_with_resource():

    ddb = boto3.resource("dynamodb")
    ddb.Table(TABLE_NAME).update_item(
        Key={
            "PK": "SITE_ENTRY"
        },
        UpdateExpression="SET #site.#enabled = :update_value",
        ExpressionAttributeNames={
            "#site": "site",
            "#enabled": "enabled"
        },
        ExpressionAttributeValues={
            ":update_value": True
        }
    )

I have tested both of these and they work.

Given code works fine if the map site exists already, seeing the error message, it looks like the path site doesn't exist.

We could create empty map during the create of the document, then update it easily OR We could create the map during the update "set #site =:siteValue"

Here is slightly modified query which creates the map.

const dynamodb = new AWS.DynamoDB();
let docClient = new AWS.DynamoDB.DocumentClient();

docClient.update(
  {
    TableName: "MyTable",
    Key: {
      id: "4b7020d2-2d19-4aeb-7f27e49d5bec",
      type: "80422149-c97d-4a1a-7bf20ef57056",
    },
    UpdateExpression: "set #site = :siteValue",
    ExpressionAttributeValues: {
      ":siteValue": { enable: true },
    },
    ExpressionAttributeNames: {
      "#site": "site",
    },
  },
  function (error, result) {
    console.log("error", error, "result", result);
  }
);

Here is an example for Java SDK V2 that will update root->nested->someValue

        Map<String, AttributeValue> attributeValues = new HashMap<>();
        attributeValues.put(":myValue", AttributeValue.builder().s(jsonString).build());

        UpdateItemRequest updateRequest = UpdateItemRequest.builder()
                .tableName("my_table_name")
                .key(keyToUpdate)
                .updateExpression("SET nested.someValue= :myValue")
                .expressionAttributeValues(attributeValues)
                .build();

        client.updateItem(updateRequest);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM