AWS SDK issues with DynamoDB and putItem - node.js

I am trying to use the aws-sdk to interact with AWS' dynamodb
Here is my code:
DynamoDB.putItem({
"TableName": tblName,
"Item": {
"UserId": { "N": obj.user_id.toString() },
"Identifier": { "S": obj.identifier },
"ReferralToken": { "S": obj.referral_token },
"CampaignId": { "N": obj.campaign_id.toString() },
"FirstName": { "S": obj.first_name },
"LastName": { "S": obj.last_name },
"Gender": { "S": obj.gender },
"BirthDate": { "S": obj.birthdate },
"Username": { "S": obj.username },
"MobileNumber": { "S": obj.mobile_number },
"PostalCodeText": { "S": obj.postal_code_text },
"Classification": { "S": obj.classification },
"DeliveryEmail": { "S": obj.delivery_email.toString() },
"DeliverySMS": { "S": obj.delivery_sms.toString() }
}
}, function (err, data) {
console.log(err);
console.log(data);
});
The error I am receiving is
{ [ValidationException: Supplied AttributeValue is empty, must contain exactly one of the supported datatypes]
message: 'Supplied AttributeValue is empty, must contain exactly one of the supported datatypes',
code: 'ValidationException',
time: Fri Oct 10 2014 10:15:25 GMT-0500 (CDT),
statusCode: 400,
retryable: false }
Not sure what I am doing wrong

According to the Put Item documentation,
When you add an item, the primary key attribute(s) are the only required attributes. Attribute values cannot be null. String and Binary type attributes must have lengths greater than zero. Set type attributes cannot be empty. Requests with empty values will be rejected with a ValidationException exception.
So make sure all values are non-null, and that all string lengths are greater than zero.

In my case , I got the same issue because of invalid parameter sends from mapping template.
#set($inputRoot = $input.path('$'))
{
"userId": "$input.params('userId')",
"userEmail": "$input.params('userEmail')",
"userName": "$input.params('userName')",
"userPassword": "$input.params('userPassword')"
}
Here I sent extra parameter userId , that's why error occurred .
So please check your mapping template , May be possible your doing same .

Related

How to delete documents from two collections in mongodb

As of now I am able to delete the specific files from filestorage.files collection based on query but I am trying to delete the specific chunks from filesstorage.chunks collection based on files_id. Can someone please suggest me the good approach to achieve it.
Should I use aggregations ? or any looping mechanism ?
Please find the below details
filestorage.files collection:
[{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"length": 878669,
"chunkSize": 261120,
"uploadDate": {
"$date": {
"$numberLong": "1666869418612"
}
},
"filename": "pexels-lucie-liz-3165335_2022-10-27T11-16-58.jpg",
"contentType": "image/jpeg",
"metadata": {
"originalname": "pexels-lucie-liz-3165335.jpg",
"parentFolder": {
"$oid": "636cd238692344da47f3e301"
},
"path": "files/Folder1/Folder3/pexels-lucie-liz-3165335_2022-10-27T11-16-58.jpg"
}
},
{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd4"
},
"length": 878669,
"chunkSize": 261120,
"uploadDate": {
"$date": {
"$numberLong": "1666869418612"
}
},
"filename": "nature-3165335_2022-10-27T11-16-58.jpg",
"contentType": "image/jpeg",
"metadata": {
"originalname": "nature-3165335.jpg",
"parentFolder": {
"$oid": "636cd238692344da47f3e301"
},
"path": "files/Folder1/Folder3/nature-3165335_2022-10-27T11-16-58.jpg"
}
}]
filestorage.chunks collection :
[{
"_id": {
"$oid": "635a68aa0651c2d869fc3fe6"
},
"files_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"n": 0,
"data": {
"$binary": {
"base64" : "xyz"
"subType": "00"
}
}
},
{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd5"
},
"files_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"n": 0,
"data": {
"$binary": {
"base64" : "abcd"
"subType": "00"
}
}
}]
Here is what I have tried :
delete_folder_files: async (ctx:any) => {
// here I am able to delete all the files but confused how to connect chunks schema and delete chunks // based on files_id.
await FileStorage.deleteMany({'metadata.parentFolder': ctx.params.id});
await FileChunk.deleteMany({files_id : ? })
ctx.status = HttpStatusCode.OK;
}
As I can see you are deleting the file ids . So after that you do not have any relation to delete the chunks in fileChunk collection .
Here is what I am thinking , First get all the file ids as an array and later you can delete the chunks with the folder_ids by querying them as array.
const file_ids = await FileStorage.find({'metadata.parentFolder': ctx.params.id },{_id:1}).distinct('_id');
await FileStorage.deleteMany({'metadata.parentFolder':ctx.params.id });
await FileChunk.deleteMany({files_id:{$in:file_ids}});
Note : Please check the performance of the query by uploading multiple files.

Scan for a nested Map inside a List that don't exist

I would like some help with structuring a scan via AWS CLI to get results where the "on_demand" map does not exist. The "on_demand" map is nested in other parent maps [0 , 1, 2...]. Which in turn are in the playlist List.
The conditions for the scan would be where is_offsite = true, video_type = OFFSITE and of course the troublesome condition where the "on_demand" map does not exist.
This is my table structure.
{
"Items": [
{
"playlist": {
"L": [
{
"M": {
"duration": {
"N": "46"
},
"on_demand": {
"M": {
"bucket": {
"S": "s3 Bucket"
},
"key": {
"S": "bucket url to video file"
}
}
},
"download": {
"M": {
"bucket": {
"S": "s3 bucket"
},
"key": {
"S": "bucket url to video file"
}
}
},
"status": {
"S": "on_demand"
}
},
"M": {
"duration": {
"N": "60"
},
"on_demand": {
"M": {
"bucket": {
"S": "s3 Bucket"
},
"key": {
"S": "bucket url to video file"
}
}
},
"download": {
"M": {
"bucket": {
"S": "s3 bucket"
},
"key": {
"S": "bucket url to video file"
}
}
},
"status": {
"S": "on_demand"
}
}
}
]
},
"video_type": {
"S": "OFFSITE"
},
"id": {
"S": "random hash id"
},
"is_offsite": {
"BOOL": true
},
}
]
}
Any assistance will be much appreciated.
This was accomplished by using the following:
aws dynamodb scan \
--table-name table-name \
--projection-expression "id" \
--filter-expression 'is_offsite = :os AND video_type = :vt AND attribute_not_exists(playlist[0].on_demand)' \
--expression-attribute-values '{":os": { "BOOL": true},":vt": {"S": "OFFSITE"}}'

Unable to update item on dynamoDb with aws-sdk on node.js

I'm trying to update items on my Users table. emailis my HASH key and id my RANGE
{
"accessToken": {
"M": {
"expirationDate": {
"N": "1622715427"
},
"token": {
"S": "dummy-auth-accessToken-xxx"
}
}
},
"email": {
"S": "xxx#toto.fr"
},
"firstName": {
"S": "Xxx"
},
"id": {
"S": "2"
},
"lastName": {
"S": "Yyyy"
},
"password": {
"S": "tataToto"
},
"refreshToken": {
"M": {
"expirationDate": {
"N": "1622715427"
},
"token": {
"S": "dummy-auth-refreshToken-xxx"
}
}
},
"username": {
"S": "XxxY"
}
}
I would like to update access and refresh token, so i'm doing this:
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: 'Users',
Key: { email: 'xxx#toto.fr' },
UpdateExpression: 'set #at1 = :1, #at2 = :2, #at3 = :3, #at4 = :4',
ExpressionAttributeNames: {
'#at1': 'accessToken.token',
'#at2': 'refreshToken.token',
'#at3': 'accessToken.expirationDate',
'#at4': 'refreshToken.expirationDate'
},
ExpressionAttributeValues: {
':1': 'new-dummy-auth-accessToken',
':2': 'new-dummy-auth-refreshToken',
':3': 1234567,
':4': 123456787654
},
ReturnValues: 'UPDATED_NEW'
}
dynamoDb.update(params, (err, data) => {})
but i got:
Unable to update item. Error JSON: {
"message": "The provided key element does not match the schema",
"code": "ValidationException",
"time": "2020-06-03T11:37:57.931Z",
"requestId": "PDTS2SDOEIOPMAO4VHGU6QM21JVV4KQNSO5AEMVJF66Q9ASUAAJG",
"statusCode": 400,
"retryable": false,
"retryDelay": 27.556977097280456
}
What I'm doing wrong please?
It's my bad... Need to add HASH AND RANGE key on params object
Key: {
id: "2"
email: 'xxx#toto.fr'
}
and my expressions is not good but i know how fix it :)
Ty to read x)

How to delete a element from LIST in dynamoDB

I have an atrribute with LIST data type be like:
"ketban": {
"L": [
{
"S": "01012018000007"
},
{
"S": "01012018000009"
},
{
"S": "01012018000006"
},
{
"S": "01012018000005"
}
]
}
Now i want to delete a item and result be like:
"ketban": {
"L": [
{
"S": "01012018000007"
},
{
"S": "01012018000009"
},
{
"S": "01012018000006"
}
]
}
I can do it with SET data type but not with LIST data type.
Please help me!!

Scanning DynamoDB with ConditionalOperator set to OR is still performing an AND

Per the API Docs I've got the following scan params:
var params = {
"TableName": "MyTable",
"ScanFilter": {
"id": {
"AttributeValueList": [
{
"S": "ID-A"
},
{
"S": "ID-D"
}
],
"ComparisonOperator": "IN"
},
"facilityName": {
"AttributeValueList": [
{
"S": "Name A"
}
],
"ComparisonOperator": "IN"
}
},
"ConditionalOperator": "OR"
};
dynamo.scan(params, function (err, data) {
if (err) {
console.log(err, err.stack);
} else {
console.log(JSON.stringify(data, null, 2));
}
});
Regardless of the value in the ConditionalOperator field, the scan always performs an AND. What am I doing wrong?
I would expect with the OR to see ID-A, ID-C AND ID-D. I only ever get ID-D.
If I do a plain or scan, with no ScanFilter setup this is the data:
{
"Count": 4,
"ScannedCount": 4,
"Items": [
{
"facilityName": {
"S": "Name B"
},
"id": {
"S": "ID-A"
}
},
{
"facilityName": {
"S": "Name B"
},
"id": {
"S": "ID-B"
}
},
{
"facilityName": {
"S": "Name A"
},
"id": {
"S": "ID-C"
}
},
{
"facilityName": {
"S": "Name A"
},
"id": {
"S": "ID-D"
}
}
]
}
I am able to use the Java SDK to do what you want:
public static void test() {
ScanRequest scanRequest = new ScanRequest("MyTable");
scanRequest.setConditionalOperator(ConditionalOperator.OR);
Map<String, Condition> scanFilter = new HashMap<String, Condition>();
Condition idFilter = new Condition().withComparisonOperator(ComparisonOperator.IN).withAttributeValueList(new AttributeValue("ID-A"), new AttributeValue("ID-D"));
Condition facilityNameFilter = new Condition().withComparisonOperator(ComparisonOperator.IN).withAttributeValueList(new AttributeValue("Name A"));
scanFilter.put("id", idFilter);
scanFilter.put("facilityName", facilityNameFilter);
scanRequest.setScanFilter(scanFilter);
ScanResult scanResult = dynamo.scan(scanRequest);
for(Map<String, AttributeValue> item : scanResult.getItems()) {
System.out.println(item);
}
}
I am not familar with the JS SDK that you are using. But your code seems OK.
When looking at the js doc, I notcied that ConditionalOperator is introduced in the 2012 version and it is not available in the 2011 version.
Can you verify that you are using the 12 version?

Resources