DynamoDB New Image has default Message and Id values - amazon-dynamodb

I noticed the NEW IMAGE in dynamodb stream always has these two fields:
"Message":"New item!"
"Id":"101"
These values are always there UNLESS my record itself has a Id and a Message field, in which case the default values are overridden. But since my table doesn't have "Id" and "Message" attributes, these values are ALWAYS present. Is this expected behavior?
I created sample dynamodb stream record:
Records: [
{
eventID: "1",
eventVersion: "1.0",
dynamodb: {
Keys: {
id: {
N: "101"
}
},
NewImage: {
Data: {
S: "New data!"
},
id: {
N: "99"
}
},
OldImage: {
Data: {
S: "Old data!"
},
id: {
N: "99"
}
},
StreamViewType: "NEW_AND_OLD_IMAGES",
SequenceNumber: "111",
SizeBytes: 26
},
awsRegion: "xyz",
eventName: "INSERT",
eventSourceARN: "xyz",
eventSource: "aws:dynamodb"
}
]
When unmarshalling record.dynamodb.NewImage, I get a NewImage as follows:
"NewImage":{"Message":"New item!", "Id":101, "Data":"New data!", "id":99}

Related

ConditionalExpression DynamoDb Insert

I have the below data schema for my DynamoDb table. I am trying to append list subscribers on the condition if input = name (ex: input = my-topic2). There can be many maps in the “topics” list and I need to search for the map where the name = input and from there add the subscriber to that topic.
{
“server-id”: “123345678”,
“server-name”: “my-server”
“topics”: [
{
“name”: “my-topic”,
“subscribers”: []
},
{
“name”: “my-topic2”,
“subscribers”: [] //This is what I need to append on a condition that the input = “my-topic2”
}
]
}
I have the current following paeans I am using which appends “my-topic” subscribers.
params = {
ExpressionAttributeNames: {
"#T": "topics",
"#S": "subscribers"
},
ExpressionAttributeValues: {
":vals": [
message.author.id
]
},
Key: {
'server-id': serverID
},
ReturnValues: "ALL_NEW",
TableName: tableName,
UpdateExpression: "SET #T[0].#S = list_append(#T[0].#S, :vals)"
};

Appsync 'Batch Create' Resolver gives "mapping template" error

I'm trying to create a resolver for a BatchCreateIngredients mutation I created, but when I run the mutation I'm getting an error of type MappingTemplate and I'm not sure why.
My table's name is IngredientsTable and I'm not using any cognito verification.
The mutation:
mutation batchCreateIngredient {
batchCreateIngredients(
input: [
{name: "Cookie" vegan: VEGAN glutenfree: GLUTENFREE},
{name: "Pizza", vegan: VEGAN, glutenfree: GLUTENFREE},
]) {
items{
id
name
vegan
}
}
}
The error message:
{
"data": {
"batchCreateIngredients": null
},
"errors": [
{
"path": [
"batchCreateIngredients"
],
"data": null,
"errorType": "MappingTemplate",
"errorInfo": null,
"locations": [
{
"line": 6,
"column": 3,
"sourceName": null
}
],
"message": "Item list elements can't be null for table 'IngredientTable' at path '$[tables]'"
}
]
}
The Relevant Parts of My Schema:
input CreateIngredientInput {
name: String!
vegan: Vegan!
glutenfree: GlutenFree!
popularity: Int
}
enum GlutenFree {
GLUTENFREE
CONTAINS_GLUTEN
UNKNOWN
}
type Ingredient {
name: String!
id: ID!
vegan: Vegan
glutenfree: GlutenFree
popularity: Int
}
type IngredientConnection {
items: [Ingredient]
nextToken: String
}
type Mutation {
createIngredient(input: CreateIngredientInput!): Ingredient
batchCreateIngredients(input: [CreateIngredientInput]): IngredientConnection
updateIngredient(input: UpdateIngredientInput!): Ingredient
deleteIngredient(input: DeleteIngredientInput!): Ingredient
}
enum Vegan {
VEGAN
NON_VEGAN
UNKNOWN
}
The Resolver for BatchCreateIngredients:
#set($ingdata = [])
#foreach($ing in ${ctx.args.input})
$util.qr($ingdata.add($util.dynamodb.toMapValues($item)))
#end
{
"version" : "2018-05-29",
"operation" : "BatchPutItem",
"tables" : {
"IngredientTable": $utils.toJson($ingdata)
}
}
From what I can tell, it looks like the issue is in the request mapping template. You have called the loop variable $ing, but you are passing "$item" to the toMapValues function. Can you try changing "item" to "ing" ?
And also you are passing
{name: "Cookie" vegan: VEGAN glutenfree: GLUTENFREE}
but mapping
items{
id
name
vegan
}
glutenfree is missing and id is not handled in the resolver

Add a number to a list item with DynamoDB

This is the DynamoDB table structure I'm working on:
{
"userId": "99999999-9999-9999-9999-999999999999",
"userProfile": {
"email": "myemail#gmail.com",
"firstName": "1234124",
"lastName": "123423",
},
"masterCards": [
{
"cardId": 101000000000001,
"cardImage": "logo.png",
"cardName": "VipCard1",
"cardWallet": "0xFDB17d12057b6Fe8c8c425D2DB88d8475674567"
},
{
"cardId": 102000000000002,
"cardImage": "logo.png",
"cardName": "VipCard2",
"cardWallet": "0xFDB17d12057b6Fe8c8c425D2DB88d8183454345"
},
{
"cardId": 103000000000003,
"cardImage": "logo.png",
"cardName": "VipCard3",
"cardWallet": "0xFDB17d12057b6Fe8c8c425D2DB88d8184345345"
}
],
}
I'm trying to increase the cardId field by one for the first list item with this Lambda function:
const dynamoDB = new AWS.DynamoDB({region: 'eu-central-1', apiVersion:'2012-08-10'});
const counterId="99999999-9999-9999-9999-999999999999"
const params = {
TableName:"FidelityCardsUsers",
Key: {"userId":{"S":counterId}},
UpdateExpression:"ADD #masterCards[0].#cardId :increment",
ExpressionAttributeNames:{
"#masterCards": "masterCards",
"#cardId": "cardId"
},
ExpressionAttributeValues:{":increment": {"N": "1"}}
}
dynamoDB.updateItem(params, function(err, data) {
if (err) {
console.log('error getting counter from DynamDB: ',err)
callback(err);
} else {
callback(null,data)
}
})
In return I get only a new top-level attribute named "mastercards[0].cardId[0]" with a value number set to 1.
I have tried to increment In an array and its work fine with AWS.DynamoDB.DocumentClient()
Example :
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
let params = {
TableName:'tableName',
Key: {
'venueId': 'VENUE_002'
},
UpdateExpression: "ADD #walk.#coordinates[0] :increment",
ExpressionAttributeNames: {
'#walk': 'walk',
'#coordinates': 'coordinates'
},
ExpressionAttributeValues: {
':increment': 1 // This is from the client
},
ReturnValues: 'UPDATED_NEW'
};
docClient.update(params, function (err, data) {
if (err) {
console.log('failure:updateShuttleDirection:failed');
console.log(err);
} else {
console.log('success:updateShuttleDirection:complete');
console.log(data);
}
});
Sample Data:
"walk": {
"coordinates": [
10,
20
],
"type": "Point"
},
I have tried to increment 10 to 11 and its work fine
Reading the doc here, it seems that:
the ADD action can only be used on top-level attributes, not nested
attributes.

API Gateway and DynamoDB PutItem for String Set

I can't seem to find how to correctly call PutItem for a StringSet in DynamoDB through API Gateway. If I call it like I would for a List of Maps, then I get objects returned. Example data is below.
{
"eventId": "Lorem",
"eventName": "Lorem",
"companies": [
{
"companyId": "Lorem",
"companyName": "Lorem"
}
],
"eventTags": [
"Lorem",
"Lorem"
]
}
And my example template call for companies:
"companies" : {
"L": [
#foreach($elem in $inputRoot.companies) {
"M": {
"companyId": {
"S": "$elem.companyId"
},
"companyName": {
"S": "$elem.companyName"
}
}
} #if($foreach.hasNext),#end
#end
]
}
I've tried to call it with String Set listed, but it errors out still and tells me that "Start of structure or map found where not expected" or that serialization failed.
"eventTags" : {
"SS": [
#foreach($elem in $inputRoot.eventTags) {
"S":"$elem"
} #if($foreach.hasNext),#end
#end
]
}
What is the proper way to call PutItem for converting an array of strings to a String Set?
If you are using JavaScript AWS SDK, you can use document client API (docClient.createSet) to store the SET data type.
docClient.createSet - converts the array into SET data type
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName:table,
Item:{
"yearkey": year,
"title": title
"product" : docClient.createSet(['milk','veg'])
}
};

Error in updating item in dynamodb

I have created simple table (username, password), the key is username.
the table contains one item:
{
"username" : "someuser",
"password" : "cat"
}
Now, i want to update from "cat" to "dog"
dynamodb.updateItem({
TableName: "users",
Key: { "username": { "S" : "someuser" } },
UpdateExpression : "SET password =:pass",
ExpressionAttributeValues : { ":pass" : { "S" : "dog" } }
}, function(err, data) {
if (err)
console.log(JSON.stringify(err, null, 2));
else
console.log(JSON.stringify(data, null, 2));
});
But i got error:
{
"message": "Invalid attribute value type",
"code": "ValidationException",
"time": "2015-11-14T20:22:36.381Z",
"statusCode": 400,
"retryable": false
}
Finally i have found that dynamodb javascript shell is not identical to dynamodb running on AWS.
The error above not occur on real dynamodb.
EDIT:
for example, the following works:
var params = {
TableName: config.SCRIPTTABLE,
Key: { id : { S: script.id }},
UpdateExpression: "SET title = :title, description = :desc, code = :code, tags = :tags, pub = :pub",
ExpressionAttributeValues: {
":title": { S: script.title },
":desc" : { S: script.description },
":code" : { S: script.code },
":tags" : { SS: script.tags },
":pub" : { BOOL: script.pub }
},
ReturnValues: "ALL_NEW"
};
dynamodb.updateItem(params, function(err, data) {
if (err) {
console.log(JSON.stringify(err));
context.fail('INTERNAL_SERVER_ERROR');
} else {
context.succeed();
}
});

Resources