Dynamodb - Condition Expression with ExpressionAttributeNames not working - amazon-dynamodb

Am trying to do a conditional update and since the field name is a reserved keyword, am using ExpressionAttributeNames to pass in the column name for the condition. The update part isn't working if i use the ExpressionAttributeNames. Any thoughts?
Update: {
Key: {
"pk": "sb#prd#" + productId,
"sk": productId.toString()
},
TableName: 'test',
ConditionExpression: '#minQty >= :minQty',
UpdateExpression: "set sold_count = :sold_count",
ExpressionAttributeNames: {
"#minQty" : "variant[0].items[0].availableQty"
},
ExpressionAttributeValues: {
":sold_count" : 1,
":minQty" : 1
},
}

The aliases defined in ExpressionAttributeNames can only be a single attribute name - they cannot be full paths like variant[0].items[0].availableQty.
You can do something like:
ConditionExpression: '#v[0].#i[0].#a >= :minQty',
ExpressionAttributeNames: {
"#v" : "variant",
"#i" : "items",
"#a" : "availableQty"
},

Related

DynamoDB update map value only if versions match

I have the following schema:
{
balance: {
customData: string,
version: number
}
}
I need to update balance.customData only if version == 2. Once update operation succeeds, I need to increment version by 1.
I tried the following update transaction
Update: {
Key: {
'pk': pk,
'sk': sk
},
TableName: this.config.getTable(),
UpdateExpression: 'SET #balance.#customData = :customData, #balance.#version = #balance.#version + :incr',
ConditionExpression: '#balance.#customData.#version = :version',
ExpressionAttributeNames: {
'#customData': 'customData',
'#balance': 'balance',
'#version': 'version'
},
ExpressionAttributeValues: {
':customData': balance.customData,
':version': balance.version,
':incr': {'N': 1},
}
}
But when I run this, I get ValidationException: Invalid UpdateExpression: Incorrect operand type for operator or function; operator or function: +, operand type: M
I assume I'm not providing correct syntax to increment map value.
Even if I remove increment part
Update: {
Key: {
'pk': pk,
'sk': sk
},
TableName: this.config.getTable(),
UpdateExpression: 'SET #balance.#customData = :customData,
ConditionExpression: '#balance.#customData.#version = :version',
ExpressionAttributeNames: {
'#customData': 'customData',
'#balance': 'balance',
'#version': 'version'
},
ExpressionAttributeValues: {
':customData': balance.customData,
':version': balance.version
}
}
I still get ValidationError with reason Other, which is not very helpful. Can you please help me understand what I'm doing wrong? Thanks

dynamodb add item to the array list

Using serverless-stack.
I have a table company with multiple branches:
new sst.Table(this, 'Company', {
fields: {
userId: sst.TableFieldType.STRING,
companyId: sst.TableFieldType.STRING,
companyName: sst.TableFieldType.STRING,
branches: [
{
branchId: sst.TableFieldType.STRING,
branchName: sst.TableFieldType.STRING
}
]
},
primaryIndex: {partitionKey: "userId", sortKey: "companyId"}
})
I am trying to add branch to the branches:
const branch = {
branchId: uuid.v1(),
branchName: data.branchName
}
const params = {
TableName: process.env.COMPANY_TABLE_NAME,
Key: {userId: "1", companyId: data.companyId},
UpdateExpression: "ADD #branches :branch",
ExpressionAttributeNames: { "#branches" : "branches" },
ExpressionAttributeValues: { ":branch": [branch] }
}
But I get this error:
ERROR ValidationException: Invalid UpdateExpression: Incorrect operand type for operator or function; operator: ADD, operand type: LIST, typeSet: ALLOWED_FOR_ADD_OPERAND
ValidationException: Invalid UpdateExpression: Incorrect operand type for operator or function; operator: ADD, operand type: LIST, typeSet: ALLOWED_FOR_ADD_OPERAND
ADD is only for numbers and sets. Your branches attribute is a list. So you can use SET with list_append.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.UpdatingListElements
SET #branches = list_append(#branches, :branch) is correct. But ExpressionAttributeValues should be ExpressionAttributeValues: { ":branch": {"L":[branch]}}
You can refer to https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.update_item

Scan a String Set(SS) that contains a substring

Suppose I have the following schema:
id: S
my_list: SS
With the following example record:
{
"id": "auniquestring",
"list": [
"item1",
"item11",
"item111",
"item2",
"item22",
"item3"
]
I am scanning the table with the following params:
params = {
ExpressionAttributeValues: {
":v1": {
S: item_substring
}
},
FilterExpression: "contains(list, contains(list_item, :v1))",
TableName: "MyItemsTable"
};
The basic idea is to return the record that contains a string in a list of strings, containing the queried substring.
Answer in JavaScript would be preferred.
I think your FilterExpression is not correct. Why are you nesting contains?
Have you tried FilterExpression: "contains(list,:v1)"?

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)"
};

How to add items to a map in DynamoDB

I'm using the AWS.DynamoDB.DocumentClient with nodejs (lambda functions on AWS)
I've to a db called Translations, primary key Term, sort key Category.
Basically I'm trying to write data in like this:
{
Term: 'hello_there',
Category: 'common_phrases',
Translations: {
en-ca: 'Hello There!'
}
}
and I want to update Translations Map to perhaps add another language, or just modify the en-ca portion of the object.
I've tried the following:
let params = {
TableName: 'Translations',
Key: {
Term: 'hello_there',
Category: 'common_phrases',
},
UpdateExpression:
'SET Translations.#lang = list_append(Translations, :term)',
ExpressionAttributeValues: {
':term': 'french version',
},
ExpressionAttributeNames: {
'#lang': 'fr-ca',
},
}
But I get an error about the wrong operand type.
I've tried:
UpdateExpression:
'SET Translations.#lang = :term',
ExpressionAttributeValues: {
':term': 'french version',
},
ExpressionAttributeNames: {
'#lang': 'fr-ca',
},
But this overwrites the entire contents of the Translations field. Meaning that if I already had en-ca in there, now I would only have fr-ca.
I tried this as well, but also get an operand error:
{
UpdateExpression: 'ADD Translations :term',
ExpressionAttributeValues: {
':term': { 'fr-ff': 'frenchterm' },
},
Any suggestions on how to add/update items to the Translations Map?
Your SET expression was close, try something like this:
UpdateExpression:
'SET #trans.#lang = :term',
ExpressionAttributeValues: {
':term': 'french version',
},
ExpressionAttributeNames: {
'#trans': 'Translations`,
'#lang': 'fr-ca',
},

Resources