Обновление массива JSON в AWS DynamoDB

Мой документ выглядит так:

{
  "data": {
      "eventId": "20161029125458-df-d",
      "name": "first",
      "purpose": "test",
      "location": "yokohama",
      "dateArray": [],
      "attendees": [
        {
          "attendeeId": "2016102973634-df",
          "attendeeName": "lakshman",
          "personalizedDateSelection": {}
        },
        {
          "attendeeId": "2016102973634-tyyu",
          "attendeeName": "diwaakar",
          "personalizedDateSelection": {}
        }
      ]
    }
}

Скажем, мне нужно обновить массив JSON посетителя с помощью sendeeIId: 2016102973634-df. Я пробовал много способов, используя обновление и выражение условия, но безуспешно.

Вот моя попытка:

const params = {
  TableName: "event",
  Key: {
    "eventId": eventId 
  },
  UpdateExpression: "SET attendees[???] = ",
  ConditionExpression: attendees.attendeeId = "2016102973634-df", 
  ExpressionAttributeValues: {
    ":attendee" : attendeeList
  },
  ReturnValues: "ALL_NEW"
};


dynamo.update(params, (err, data) => {
  if (err) {
    return reject(err);
  }
  console.log(data.Attributes);
});

Не удалось найти ресурсы для обновления Json в массиве.

После комментария @notionquest: - Не использовал JsonMarshaller. Изначально я добавил пустой массив в поле для посетителей следующим образом:

{
  "eventId": "20161029125458-df-d",
  "name": "first",
  "purpose": "test",
  "location": "yokohama",
  "dateArray": [],
  "attendees": []
}

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

const attendee = {
  "attendeeName": "user1",
  "personalizedDateSelection": {"today": "free"}
}
const attendeeList = [attendee];
const eventId = "20161029125458-df-d";


const params = {
  TableName: "event",
  Key: {
    "eventId": eventId
  },
  UpdateExpression: "SET attendees = list_append(attendees, :attendee)",
  ExpressionAttributeValues: {
    ":attendee" : attendeeList
  },
  ReturnValues: "ALL_NEW"
};


dynamo.update(params, (err, data) => {
  if (err) {
    return reject(err);
  }
  console.log("in update dynamo");
  console.log(data.Attributes);
});

Как вы видели в приведенных выше фрагментах, изначально я добавляю пустой массив [] и добавляю нового участника, используя приведенный выше код. Теперь, как мне обновить конкретный JSON в массиве. Если вы говорите, что это невозможно, что еще я могу попробовать?

Должен ли я попробовать это:

  1. Получить полный JSON.
  2. Манипулируйте JSOn и меняйте то, что я хочу, в моем nodeJS.
  3. А затем обновите новый JSON до DynamoDB.
  4. Но это потребует два вызова DynamoDB, который кажется неэффективным.

Хотелось бы узнать, есть ли какой-нибудь обходной путь?

2 ответа

Решение

Я не смог найти никакого ответа на запрос и обновить JSON-массив. Я думаю, что это может быть прибыльным мотивом AWS, чтобы не допустить эти функции. Если вам нужно выполнить запрос по определенному идентификатору, отличному от первичного ключа, вам необходимо создать вторичный индекс, который будет рентабельным. Эта вторичная стоимость индекса является дополнительной к стоимости таблицы dyn amoDB.

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

{
  "data": {
      "eventId": "20161029125458-df-d",
      "name": "first",
      "purpose": "test",
      "location": "yokohama",
      "dateArray": [],
      "attendees": {
        "2016102973634-df": {
          "attendeeId": "2016102973634-df",
          "attendeeName": "lakshman",
          "personalizedDateSelection": {}
        },
        "2016102973777-df": {
          "attendeeId": "2016102973777-df",
          "attendeeName": "ffff",
          "personalizedDateSelection": {}
        }
      }
    }
}

Изменение участников с [] на {}. Это позволяет мне гибко запрашивать конкретный посетитель и изменять весь JSON, связанный с этим. Несмотря на то, что это лишний шаг, я не хочу тратить лишние деньги на мой хобби-проект.

Пример запроса на обновление:

Структура данных (сохранена в DynamoDB)

{
  tenant_id: 'tenant_1',
  users: {
    user1: {
      _id: 'user1',
      email_address: 'test_email_1@gmail.com'
    },
    user2: {
      _id: 'user2',
      email_address: 'test_email_2@gmail.com'
    }
  }
}

Данные для обновления (используются в параметрах)

var user = {
 email_address: 'updated@gmail.com'
}

Params

var params = {
    TableName: 'tenant-Master',
    Key: {
       "tenant_id": 'tenant_1'
    },
    UpdateExpression: "set #users.user1 = :value",
    ExpressionAttributeNames: {
    "#users": "users"
    },
    ExpressionAttributeValues: {
    ":value": user,
    },
 };

Объяснение

Переключившись на карту карт из массива карт, мы теперь можем использовать UpdateExpression: "set #users.user1 = :value" для обновления нашего вложенного объекта на карте пользователей с идентификатором user1.

ПРИМЕЧАНИЕ. Этот метод как есть ЗАМЕНЯЕТ весь объект карты вusers.user1. Если вы хотите сохранить уже существующие данные, необходимо внести некоторые изменения.

Вы можете хранить индекс списка. при обновлении списка мы можем их использовать. Например,

{


"data": {
      "eventId": "20161029125458-df-d",
      "name": "first",
      "purpose": "test",
      "location": "yokohama",
      "dateArray": [],
      "attendees": [
        {  
          "index":0,  
          "attendeeId": "2016102973634-df",
          "attendeeName": "lakshman",
          "personalizedDateSelection": {}
        },
        {
           "index":1,
          "attendeeId": "2016102973634-tyyu",
          "attendeeName": "diwaakar",
          "personalizedDateSelection": {}
        }
      ]
    }
}
const params = {
  TableName: "event",
  Key: {
    "eventId": eventId 
  },
  UpdateExpression: "SET attendees[attendee.index].attendeeName = :value",
  ExpressionAttributeValues: {
    ":value" : {"S":"karthik"}
  },
  ReturnValues: "ALL_NEW"
};


dynamo.update(params, (err, data) => {
  if (err) {
    return reject(err);
  }
  console.log(data.Attributes);
});
Другие вопросы по тегам