Adding multiple DynamoDB items through terraform - amazon-dynamodb

How to add multiple items in dynamoDB table?
table_name = "${var.environment}-kaleidos-dynamodb-MappingConfig"
hash_key = "eventType"
item = <<EOF
json
EOF
}````
DynamoDB always expects one item. Is there a way to provide multiple items?

There's no way to add multiple items using a single resource "aws_dynamodb_table_item". You can have multiple resource statements in the same file, as long as you give them different names, for example:
resource "aws_dynamodb_table_item" "item1" {
...
}
resource "aws_dynamodb_table_item" "item2" {
...
}
If you are trying to create items based on an array or map or a specific number, you can use count or for_each (for_each was introduced in 0.12.6)
count example:
resource "aws_dynamodb_table_item" "items" {
count = 4
item <<EOF
{
"pk": {"S": "${count.index}"}
}
EOF
for_each example:
resource "aws_dynamodb_table_item" "items" {
for_each = {
item1 = {
something = "hello"
}
item2 = {
something = "hello2"
}
}
item = <<EOF
{
"pk": {"S": "${each.key}"},
"something": {"S": "${each.value.something}"}
}
EOF
}

If someone is looking to insert set datatype here is an example
resource "aws_dynamodb_table_item" "employee" {
table_name = "${var.environment}-employee"
hash_key = "id"
for_each = {
"1234abcd" = {
fistName = "Jack"
lastName = "Dorsey"
projects = ["Twiter", "Square"]
}
"34589fsd" = {
fistName = "Jack"
lastName = "MA"
projects = ["Alibaba", "Ant"]
}
}
item = <<ITEM
{
"id": {"S": "${each.key}"},
"fistName": {"S": "${each.value.fistName}"},
"lastName": {"S": "${each.value.lastName}"},
"projects": {"SS": ${jsonencode(each.value.projects)}}
}
ITEM
}

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

Querying Cosmos Nested JSON documents

I would like to turn this resultset
[
{
"Document": {
"JsonData": "{\"key\":\"value1\"}"
}
},
{
"Document": {
"JsonData": "{\"key\":\"value2\"}"
}
}
]
into this
[
{
"key": "value1"
},
{
"key": "value2"
}
]
I can get close by using a query like
select value c.Document.JsonData from c
however, I end up with
[
"{\"key\":\"value1\"}",
"{\"key\":\"value2\"}"
]
How can I cast each value to an individual JSON fragment using the SQL API?
As David Makogon said above, we need to transform such data within our app. We can do as below:
string data = "[{\"key\":\"value1\"},{\"key\":\"value2\"}]";
List<Object> t = JsonConvert.DeserializeObject<List<Object>>(data);
string jsonData = JsonConvert.SerializeObject(t);
Screenshot of result:

Passing object as array in body in proto3

I'm wondering how I can pass an array as the body of the message without having to specify a key. I can easily do:
message TypeResponse {
message Type {
string ID = 1;
string Name = 2;
string Description = 3;
string IsMobile = 4;
string IsTablet = 5;
string IsDesktop = 6;
}
repeated Type types = 1;
}
That would response with:
{
"types": [
{
"ID": 1
...
}
]
}
I'd like to structure my response as the following to match my REST API:
[
{
"ID": 1
...
},
{
"ID": 2
...
}
]
Proto requires that the top level concept is a message, which spills into the JSON mapping.
Something you could do is just skip the first characters until you reach a [ character, and then drop the very last character which will be a ]. The output format for JSON is specified by the Proto3 spec, so you can reasonably depend on the format.

ASP.Net Core - Get All data of a post form

I want to save all data of a form.
My form has these elements-
( Using Postman Plugin )
My controller is like this-
[HttpPost]
public async Task<IActionResult> Insert(IFormCollection data)
{
return Ok(data);
}
So, I am getting something like this-
[
{
"key": "user_id",
"value": [
"'12'"
]
},
{
"key": "title",
"value": [
"123"
]
},
{
"key": "text[]",
"value": [
"werwer",
"ghj"
]
}
]
I want to get the value of texts.
So, for this case-
"werwer",
"ghj"
So, I have tried something like this-
foreach (string description in data["text"])
{
// description => empty
}
and also tried this-
data.text
and also-
data->text
But nothing works for me.
Can anyone please help?
Thanks in advance for helping.
Why not loop through each keys and if the key is "text", get the values. Since the value is a comma seperated string, you can call the Split method on that to get an array which contains 2 items( from your sample input).
foreach (string description in data.Keys)
{
if (description.Equals("text"))
{
var v = data[description];
var stringItems = v.Split(',');
foreach (var stringItem in stringItems)
{
//do something with stringItem
}
}
}
BTW, the key should be text, not text[]. Even if you have muliple input fields with the same name "text", when you submit, It will be a single key ("text") with 2 items int he value property
{
"key": "text",
"value": [
"werwer",
"ghj"
]
}

how to add an empty or data map in dynamodb?

I have something like this:
{
Records:{}
}
and I just want to add data inside records like this:
{
Id: 123,
Records:{
10001: { event : "item1" }
}
}
My 1st attempt:
var params = {
TableName : "Records",
Key : { Id : 123 },
UpdateExpression: 'set Record.#k1.event = :v1',
ExpressionAttributeNames: { '#k1' : 10001},
ExpressionAttributeValues: { ':v1' : 'item1' }
};
Because Record.10001 doesn't exist, it give me error:
The document path provided in the update expression is invalid for update
"ADD" only support NUMBER and SET type so its not suitable in my case.
My 2nd attempt (trying to create a empty map 1st):
var params = {
TableName : "Records",
Key : { Id : 123 },
UpdateExpression: 'set Record.#k1 = {}',
ExpressionAttributeNames: { '#k1' : 10001},
};
It fails as my syntax is probably incorrect and I cannot find how to create a empty map to an attribute.
So my question is how do I add structured object as a map or empty map to an existing item like the example above?
I can easily modifying the data from the amazon DynamoDB data management page so at least I know there exist a way to do it. I just need to know how.
Thanks
I somehow successfully done it this way:
var params = {
TableName: "Records",
Key: { Id: 123 },
UpdateExpression: 'set Records.#k1 = :v1',
ExpressionAttributeNames: {'#k1': '10001',},
ExpressionAttributeValues: {':v1': { event: 'Yay~' } }
};
optionally you could use
UpdateExpression: 'set Records.#k1 = if_not_exists( Records.#k1, :v1)',
to avoid overwriting existing records.
I found a workaround for the error we get.
try:
table.update_item(
Key = {'Id' : id},
UpdateExpression = 'SET Records.#key1.#key2 = :value1',
ExpressionAttributeNames = {'#key1': '10001', '#key2' : 'event'},
ExpressionAttributeValues = {':value1': 'singing'}
)
except:
table.update_item(
Key = {'Id' : id},
UpdateExpression = 'SET Records = :value1',
ExpressionAttributeValues = {':value1': {'10001': {'event' : 'dance'}}}
)
When we try to update for the first time we get "The document path provided in the update expression is invalid for update" error. An exception will be thrown since there will be no nested JSON.
Thereafter, any updates say for example Record.10002 will not throw exception. Update function in the try block will be executed.
Please comment on this if this is the correct way of handling this kind of scenario.
one of the possible resolution to get rid of such problem: you have to have an empty object created and exist in DB in advance.
for instance,
during generation of your object (original creation in DB):
field: { }
to update this field use:
TableName: ....,
Key: {
.....
},
UpdateExpression: 'set field.#mapKey = :v',
ExpressionAttributeNames: {
'#mapKey': myName
},
ExpressionAttributeValues: {
':v': myValue
}
This can be done in c# as follows.
If you have the following json:
"invoice":{
"M":{
":number":{
"S":"XPN1052"
}":date":{
"S":"02-17-2022"
}
}
}
You can use the following code to insert an invoice record:
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":invoice", new AttributeValue { M = new Dictionary<string, AttributeValue>{
{":date", new AttributeValue { S = invoice.TxnDate.ToString("MM-dd-yyyy") }},
{":number", new AttributeValue{ S = invoice.DocNumber } } }
} }},
UpdateExpression = "SET invoice = :invoice",
var params = {
TableName : "Records",
Key : { Id : 123 },
UpdateExpression: 'set #Records = :obj',
ExpressionAttributeNames: { '#Records' : 'Records'},
ExpressionAttributeValues: { ':obj' : {'10001': { 'event' : 'item1' }}}
};
In order to insert/update Dynamodb items dynamically based on a given dictionary with various keys (eventually columns in Dynamodb) we can construct query string as shown below:
# given dictionary with needs to be dumped into dynamodb
dict_to_insert = {'column1':'value1',
'column2.subdocument1':{'subkey1':'subvalue1',
'subkey2':'subvalue2'}...}...
# placeholder variables
# Using upsert for insert/update mllog records on dynamodb
query = "SET"
values_dict = {}
names_dict = {}
i = 0
# iterating over given dictionary and construct the query
for key, value in dict_to_insert.items():
# if item key column provide in the given dictionary
# then it should be skipped
if key == 'ITEM_KEY_NAME':
i += 1
continue
# None values causing error on update_item
# So, better to ignore them as well
if value is not None:
# if_not_exists method prevents overwriting existing
# values on columns
query += " " + "#k_" + str(i) + " = if_not_exists(#k_" + str(i) + \
", :v_" + str(i)+")"
if key != list(dict_to_insert.keys())[-1]: # if not the last attribute add ,
query += ","
# Defining dynamodb columns and their corresponding values
values_dict["#k_" + str(i)] = key
names_dict[":v_" + str(i)] = value
i += 1
Once we construct the query string as shown above, then we can confidently run our update_item method on Dynamodb:
# table obj here is boto3 dynamodb resource instance
table.update_item(
TableName='DYNAMODB_TABLENAME',
Key={'ITEM_KEY_NAME': 'ANY_VALUE_AS_KEY'},
UpdateExpression=query.strip(),
ExpressionAttributeNames=names_dict,
ExpressionAttributeValues=values_dict)

Resources