AWS SDK in javascript - BatchWriteItemCommand - String array imported as string set not a array of strings

0

I am inserting an dynamodb record which contains an array and it is coming up as a DynamoDB StringSet, rather than a List of strings. i am using


import {
  DynamoDBClient,
  BatchWriteItemCommand,
  ScanCommand,
} from "@aws-sdk/client-dynamodb";
import dbDataTypes from "dynamodb-data-types";

const REGION = "ap-southeast-2";
const dbclient = new DynamoDBClient({ region: REGION });
export function buildPutStatement(data) {
  let dynamoDBRecords = data.map((record) => {
    record = dbDataTypes.AttributeValue.wrap(record);
    let dynamoRecord = Object.assign({ PutRequest: { Item: record } });
    return dynamoRecord;
  });
  return dynamoDBRecords;
}

try {
  const tableName = "shipmentData";
  let records = [{
    modifiedAt: "2023-02-16T04:37:45.826Z",
    modifiedBy: "test script Feb 2023",
    shipmentId: "11122a56-0b8c-4a14-ba70-f5d7dfa6b22f",
    tag: "AportGuids",
    value: {
      timestamp: 1676522265826,
      guids: [
        "07088ea1-cb53-4bd3-b7a7-2a1fdf1e99ca",
        "30dce880-0b00-4682-b612-4b54dbf7caef",
      ],
    },
  }];

  const putStatements = buildPutStatement(records);

  let requestItems = {};
  requestItems[tableName] = putStatements;

  var params = {
    RequestItems: requestItems,
  };

  await dbclient.send(new BatchWriteItemCommand(params));

  console.log(records?.length + " Records processed");
} catch (err) {
  console.log("Error", err);
}

It is getting converted to dynamo Db Json format with an SS (String Set) as follows...

 "modifiedBy": {
    "S": "test script Feb 2023"
  },
  "value": {
    "M": {
      "guids": {
        "SS": [
          "07088ea1-cb53-4bd3-b7a7-2a1fdf1e99ca",
          "30dce880-0b00-4682-b612-4b54dbf7caef"
        ]
      },
      "timestamp": {
        "N": "1676522265826"
      }

rather than an L or S (Strings)...

"value": {
  "M": {
   "disportGuids": {
    "L": [
     {
      "S": "1dc8a478-d2af-4d84-ba57-4b1be4fb3c7c"
     },
     {
      "S": "dbe47150-1940-44cf-a264-421e63f0aacd"
     }
    ]
   },
   "timestamp": {
    "S": "1676273448403"
   }

This L of S (List of Strings) is what i get when i post through my web portal via AppSync. Note this is returned as a String[] in the json.

The main issue is when i retreive it in my lambda with the following...

const p = new Promise<any[]>((resolve, reject) => {
      this.ddb.query(
        {
          ExpressionAttributeValues: {
            ":v1": id,
          },
          KeyConditionExpression: "id = :v1",
          TableName: this.sourceTable,
        },
        (err: any, data: any) => {

i cannot iterate through it as it comes out in a different format again. e.g.

{ "values":{
    "type": "String",
     "values": ["1dc8a478-d2af-4d84-ba57-4b1be4fb3c7c", "dbe47150-1940-44cf-a264-421e63f0aacd"],
     "wrapperName": "Set"
}}

rather then just... ["1dc8a478-d2af-4d84-ba57-4b1be4fb3c7c", "dbe47150-1940-44cf-a264-421e63f0aacd"]

Notes/questions?

  1. In the AWS console when I edit the record, the "View DynamoDB JSON" toggle is disabled. Why is this? I assume it thinks it is corrupted.
  2. if I append a null to the array before posting it, it comes out in the desired format, but then I have a null in the array which I will have to code for.
  3. How to i get it to store in the desired format e.g. a string[]?
  • We can't help you without seeing how you write the item. Can you share your Appsync function.

  • i have added some more information to the question. I am also using graphQL to pull it down in my web portal. With GraphQL the array comes out in the same format whether it is stored in dynamo Db as SS or L of S.

  • Let me get this correct, items which you store via AppSync are storing as String Sets, which impacts how you consume those items in Lambda? If thats correct, please share how you store the items using AppSync, as the issue belongs there, not while reading.

  • No, the BatchWriteItemCommand is resulting in it being stored as a String Set. I have updated the question with the insert code.

  • It is this like that does it..... record = dbDataTypes.AttributeValue.wrap(record);

1 Answer
1

You can explicitly set the data type like below:

const opts = { types: { alphabets: 'L' } };

dbDataTypes.AttributeValue.wrap(guids,opts)
profile pictureAWS
EXPERT
answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions