Как обновить несколько атрибутов элемента в DynamodB с помощью Boto3 - PullRequest
0 голосов
/ 26 июня 2018

Я пытаюсь обновить несколько атрибутов одного элемента из таблицы в DynamoDB. Мой код написан на Python 3. Каждый раз, когда я пробую его, я получаю несколько ошибок, связанных с выражением обновления и способом его написания. Я проверил документацию и примеры на сайте AWS, но запутался в одном шаге, связанном с AttributeUpdates.

Это индекс таблицы, созданной в Node.js (я никак не могу ее изменить):

const Pages = dynamodb.define('Page', {
  hashKey : 'idPages',
  timestamps : true,//creates 2 string variables "createdAt" & "updatedAt"
  schema : {
    idPages : dynamodb.types.uuid(),//assigns one unique ID it is a string also
    url: Joi.string(),
    var1InTable: Joi.string(),//want to update this
    idSite: Joi.string(),
    var2InTable: Joi.array().allow(null)//want to update this
  },
  indexes: [
    {
      hashKey: 'idSite',
      rangeKey: 'url',
      name: 'UrlIndex',
      type : 'global'
    }
  ]
});

Мои переменные для обновления имеют два вида: строки и список строк:

dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
tb_pages=dynamodb.Table('pages')
idPages="exampleID123"#hash key 
url="www.example.com"#range key
var1String="example string"
var2StrList=["Example","String","List"]
var3NewString="new string variable"

Итак, я проверил пример в Amazon и следовал его структуре:

        response=tb_pages.update_item(
            Key={
                    'idPages':item['idPages'],
                    'url':item['url']
                    },
            UpdateExpression="SET var1InTable= :var1, var2InTable= :var2,var3InTable= :var3",
            AttributeUpdates={
                    ':var1': var1String,
                    ':var2': var2StrList,
                    ':var3': var3NewString
                    },
            ReturnValues="UPDATED_NEW"

                )

Я получил следующую ошибку для всех переменных в AttributeUpdates:

Invalid type for parameter AttributeUpdates.:var1, value: example string, type: <class 'str'>, valid types: <class 'dict'>

Итак, я следовал документации AWS boto3 и заменил переменные словарями, в которых код типа переменной является ключом, а переменная - значением.

        response=tb_pages.update_item(
            Key={
                    'idPages':item['idPages'],
                    'url':item['url']
                    },
            UpdateExpression="SET var1InTable= :var1, var2InTable= :var2,var3InTable= :var3",
            AttributeUpdates={
                    ':var1': {"S":var1String},
                    ':var2': {"L":var2StrList},
                    ':var3': {"S":var3NewString},
                    },
            ReturnValues="UPDATED_NEW"

                )

И получил следующую ошибку:

ParamValidationError: Parameter validation failed:
Unknown parameter in AttributeUpdates.:var1: "S", must be one of: Value, Action
Unknown parameter in AttributeUpdates.:var2: "L", must be one of: Value, Action
Unknown parameter in AttributeUpdates.:var3: "S", must be one of: Value, Action

Еще раз я проверил документацию, но запутался в том, где поставить действие и какой использовать.

Примечание: Я могу изменить список строк на набор строк или объединить их в одну строку, чтобы упростить задачу, так как я не знаю, какой тип объектов Python совместим с Joi.array().allow(null) объект, определенный в Node.js.

1 Ответ

0 голосов
/ 28 июня 2018

После нескольких попыток и прочтения документации API Dynamodb я обнаружил, что метод PutItem:

Создает новый элемент или заменяет старый элемент новым. Если элемент, имеющий тот же первичный ключ, что и новый элемент, уже существует в указанной таблице, новый элемент полностью заменяет существующий элемент.

Это может быть не оптимально, но при использовании putItem с теми же ключами и значениями можно заменить весь элемент, в этом случае

        tb_pages.put_item(
            Item={
                    'idPages':item['idPages'],#hash key
                    'url':item['url'],#range key
                    'var1InTable':var1String,
                    'var2InTable':var2StrList,
                    'var3InTable':var3NewString,
                    'otherAttributeToKeep':item['otherAttributeToKeep']#see the note
                    }
            )

примечание: Не забудьте снова передать все атрибуты элемента, поскольку этот метод перезапишет элемент, в противном случае они будут перезаписаны и удалены.

Edit:

Проблема с кодом в том, что я использовал AttributeUpdate вместо ExpressionAttributeValues, как только я изменил его, и в качестве кода (потому что url является зарезервированным словом) в коде он работал нормально

response=tb_pages.update_item(
    Key={
            'idPages':item['idPages'],
            'urlz':item['urlz']
            },
    UpdateExpression="SET var1InTable= :var1, var2InTable= :var2,var3InTable= :var3",
    ExpressionAttributeValues={
            ':var1': var1String,
            ':var2': var2StrList,
            ':var3': var3NewString
            },
    ReturnValues="UPDATED_NEW"

        )
...