создать или обновить Dynamodb - PullRequest
6 голосов
/ 11 июля 2020

В настоящее время я проверяю, существует ли элемент с запросом, а затем использую put или updateItem, я хочу изменить его и сделать один вызов DDB. Я хочу сделать запрос, который обновит или создаст элемент.

Вот пример моего элемента:

{
   id: 'dsfadsf'
   fa: { "apple" : { "S" : "76-100" }, "yolo" : { "S" : "0-25" }
   pa: { "finish" : { "BOOL" : false },    "userKey" : { "S" : "3e299e12-9e66" }  }
   createdAt: 32432432423
}

типы элементов:

createdAt - Number
fa - Map
pa - Map
id - String
finish - Boolean
key - String

Если элемент существует, я хочу создать sh новый элемент, например {papa: 'dsfadsf'} (никогда не изменять существующий элемент внутри карты fa) и изменить значение fini sh внутри карты pa

Это пункт после обновления:

{
   id: 'dsfadsf'
   fa: { "apple" : { "S" : "76-100" }, "yolo" : { "S" : "0-25" }, "papa": { "S" : "dsfadsf"} }
   pa: { "finish" : { "BOOL" : true },    "userKey" : { "S" : "3e299e12-9e66" }  }
   createdAt: 32432432423
}

Вот что я пробовал, но не работает

{
    TableName: tableName,
    Key: {
      id: "dsfadsf",
    },
    UpdateExpression: `SET #id = :id, fa.${itemName} = if_not_exists(fa.${itemName}, :text), pa.finish = if_not_exists(pa.finish, :finishval), #ca = :ca`,
    ExpressionAttributeNames: {
      "#id": "id",
      "#ca": createdAt
    },
    ExpressionAttributeValues: {
      ":id": "7fd9a81b-7a7c-4cfb-9c84-25dc2798a8f7",
      ":text": itemText,
      ":finishval": true,
      ":ca": 32432432423
    },
    ConditionExpression: `attribute_not_exists(id)`,
  };

1 Ответ

1 голос
/ 14 июля 2020

TL; DR

Это невозможно с текущей структурой вашего элемента. Измените fa и pa на наборы строк, избавьтесь от finish: true и используйте выражение обновления ADD.

Это невозможно с текущей структурой вашего предмета. Вот почему - чтобы соответствовать вашим требованиям, UpdateExpression должен иметь форму:

if "fa" exists, add {"papa":"dsfadsf"} to it
else, create new "fa"={"papa":"dsfadsf"}

Из всех выражений обновления DynamoDB в этом сценарии можно использовать только SET и ADD. .

Вышеупомянутое условие if else не может быть выражено в UpdateExpression с помощью SET по следующим причинам:

  • SET fa.papa = 'dsfadsf' обновит fa, если он существует, но если его нет, вы получите ошибку The document path provided in the update expression is invalid for update.

  • SET fa = {"papa":"dsfadsf"} создаст новый fa, но перезапишет его, если он существует.

Если вы попытаетесь объединить ADD & SET для достижения вышеуказанного условия if else во что-то вроде ADD fa {} SET fa.papa = dsfadsf, вы получите ошибку Two document paths overlap with each other; must remove or rewrite one of these paths

Итак, мы только осталось с выражением ADD, но ADD работает только с наборами. Поэтому, если вы можете позволить себе превратить содержимое fa & pa в наборы строк, вы можете достичь своей цели «создать или обновить в 1 go». Вот как это будет работать:

Исходная структура элемента должна быть:

{
  "ca": 32432432423,
  "fa": [
    "apple:76-100",
    "yolo:0-25"
  ],
  "id": "dsfadsf",
  "pa": [
    "key:9e66"
  ]
}

В DynamoDB JSON это:

{
  "ca": {
    "N": "32432432423"
  },
  "fa": {
    "SS": [
      "apple:76-100",
      "yolo:0-25"
    ]
  },
  "id": {
    "S": "dsfadsf"
  },
  "pa": {
    "SS": [
      "key:9e66"
    ]
  }
}

Теперь, используя следующий код:

let AWS = require("aws-sdk")
let docClient = new AWS.DynamoDB.DocumentClient()
docClient.update({
    TableName: "my-table",
    Key: { id: "dsfadsf" },
    UpdateExpression: `ADD fa :fa, pa :pa SET ca = :ca`,
    ExpressionAttributeValues: {
        ":fa": docClient.createSet(["papa:dsfadsf"]),
        ":pa": docClient.createSet(["finished"]),
        ":ca": 32432432423
    }
}

Если элемент с id "dsfadsf" уже существует, он обновляется следующим образом:

{
  "ca": {
    "N": "32432432423"
  },
  "fa": {
    "SS": [
      "apple:76-100",
      "papa:dsfadsf",
      "yolo:0-25"
    ]
  },
  "id": {
    "S": "dsfadsf"
  },
  "pa": {
    "SS": [
      "finished",
      "key:9e66"
    ]
  }
}

Если элемент с id " dsfadsf "НЕ существует, он создается следующим образом:

{
  "ca": {
    "N": "32432432423"
  },
  "fa": {
    "SS": [
      "papa:dsfadsf"
    ]
  },
  "id": {
    "S": "dsfadsf"
  },
  "pa": {
    "SS": [
      "finished"
    ]
  }
}
...