Можно ли сделать условный ввод или обновление в DynamoDB?

Скажем, что я храню записи со следующей структурой в DynamoDB:

{    
    "id": "57cf5b43-f9ec-4796-9de6-6a50f556cfd8",
    "created_at": "2015-09-18T13:27:00+12:00",
    "count": 3
}

Теперь можно ли выполнить одно из следующих требований:

  • если запись с данным id не существует, она должна быть создана с count = 1
  • если запись для этого id существует, счетчик обновляется.

В настоящее время я делаю запрос, чтобы проверить, если запись существует, и в зависимости от результата я делаю put или update. Было бы неплохо сбросить это на одну операцию.

Ответ 1

Вы можете сделать это с UpdateItem API-интерфейса UpdateItem и UpdateExpression из-за вашего UpdateExpression использования. Поскольку count будет здесь типом Number, вы можете использовать выражения SET или ADD:

Документация для ADD сообщает вам, что вы можете использовать ее для типов Number (выделение мое):

  • ADD - добавляет указанное значение к элементу, если атрибут еще не существует. Если атрибут существует, то поведение ADD зависит от типа данных атрибута:

    • Если существующим атрибутом является число, и если Value также является числом, тогда значение математически добавляется к существующему атрибуту. Если Value - отрицательное число, то оно вычитается из существующего атрибута.

    Если вы используете ADD для увеличения или уменьшения значения числа для элемента, который не существует до обновления, DynamoDB использует 0 в качестве начального значения. Аналогично, если вы используете ADD для существующего элемента для увеличения или уменьшения значения атрибута, которое не существует до обновления, DynamoDB использует 0 в качестве начального значения. Например, предположим, что элемент, который вы хотите обновить, не имеет атрибута с именем itemcount, но вы все равно должны ADD номер 3. DynamoDB создаст атрибут itemcount, установит его начальное значение на 0 и, наконец, добавит 3 к нему. Результатом будет новый атрибут itemcount в элементе со значением 3.

Для вашего примера вы можете иметь UpdateExpression как ADD #c :n, где :n имеет ExpressionAttributeValue типа Number, 1 - это значение, а #c - подстановка ExpressionAttributeName для count. Вам нужно использовать заполнитель для count потому что это зарезервированное слово.

Дополнительные примеры по изменению элементов и атрибутов с помощью выражений обновления

Ответ 2

То, о чем я не упоминал в моем вопросе, было то, что я хотел, чтобы count пошел на последующие события, не изменяя created_at. Мой последний рабочий UpdateInput выглядит следующим образом:

{
  Key: {
    id: {
      S: "some_unique_id"
    }
  },
  TableName: "test",
  ExpressionAttributeNames: {
    #t: "created_at",
    #c: "count"
  },
  ExpressionAttributeValues: {
    :t: {
      S: "2015-09-26T15:58:57+12:00"
    },
    :c: {
      N: "1"
    }
  },
  UpdateExpression: "SET #t = if_not_exists(#t, :t) ADD #c :c"
}