I have a dynamodb table with a partition key id and a sort key value
Now I want to run batchWriteItem to insert multiple items with the same partition key and a different sort key but it only inserts the last item:
$response = $dynamoDb->batchWriteItem([
'RequestItems' => [
'mytable' => [
[
'PutRequest' => [
'Item' => [
'id' => array('S' => '123abc'),
'value' => array('N' => '1'),
],
'Item' => [
'id' => array('S' => '123abc'),
'value' => array('N' => '2'),
],
'Item' => [
'id' => array('S' => '123abc'),
'value' => array('N' => '3'),
]],
],
],
],
]);
With this code only the item with the value 3 gets inserted
"Items": [
{
"id": {
"S": "123abc"
},
"value": {
"N": "3"
}
}
],
Is there something wrong with the code or something I didn't consider?
It perfectly works when doing single requests:
$response = $dynamoDb->putItem(array(
'TableName' => 'mytable',
'Item' => array(
'id' => array('S' => '123abc'),
'value' => array('N' => '1'),
),
));
$response = $dynamoDb->putItem(array(
'TableName' => 'mytable',
'Item' => array(
'id' => array('S' => '123abc'),
'value' => array('N' => '2'),
),
));
$response = $dynamoDb->putItem(array(
'TableName' => 'mytable',
'Item' => array(
'id' => array('S' => '123abc'),
'value' => array('N' => '3'),
),
));
Is there any performence difference between batchWriteItem or doing 3 single putItem reuests in sequence?
You are using incorrect syntax for batchWrite, try following
$response = $dynamoDb->batchWriteItem([
'RequestItems' => [
'mytable' => [
[
'PutRequest' => [
'Item' => [
'id' => array('S' => '123abc'),
'value' => array('N' => '1'),
]
],
'PutRequest' => [ ///Entire PutRequest array need to be repeated not just item array///
'Item' => [
'id' => array('S' => '123abc'),
'value' => array('N' => '2'),
]
],
],
],
],
]);
Apart from that, the difference between single insert and multiple inserts would be the call to connect with DynamoDB, in batchPut you will send entire array at once whereas in single insert it will connect to DB each time it tries to perform any operation.
In general, you can use Batch to process things faster.
Here is the refernce link for batchWrite syntax
Hope that helps.
Related
I am trying to update a field in a record in Timestream but it keeps inserting new record instead.
Here is my code:
$dimensions= [];
$dimensions[] = [
'Dimensions' => [
[
'DimensionValueType' => 'VARCHAR',
'Name' => 'id',
'Value' => '123456',
],
[
'DimensionValueType' => 'VARCHAR',
'Name' => 'remark',
'Value' => 'Remark test text',
],
],
];
$query = [
'CommonAttributes' => [
'MeasureName' => 'table_cnt',
'MeasureValue' => 'table_cnt',
'MeasureValueType' => 'VARCHAR',
'Time' => '1651501311000',
'TimeUnit' => 'MILLISECONDS',
'Version' => 1,
],
'DatabaseName' => 'mydb',
'Records' => $dimensions,
'TableName' => 'table',
];
$db->WriteRecords($query);
and now here how I try to upsert the same record inserted above:
$dimensions= [];
$dimensions[] = [
'Dimensions' => [
[
'DimensionValueType' => 'VARCHAR',
'Name' => 'id',
'Value' => '123456',
],
[
'DimensionValueType' => 'VARCHAR',
'Name' => 'remark',
'Value' => 'New Remark test text', // new text
],
],
];
$query = [
'CommonAttributes' => [
'MeasureName' => 'table_cnt',
'MeasureValue' => 'table_cnt',
'MeasureValueType' => 'VARCHAR',
'Time' => '1651501311000', // same time
'TimeUnit' => 'MILLISECONDS',
'Version' => 2, // changed to version 2 when upserting
],
'DatabaseName' => 'mydb',
'Records' => $dimensions,
'TableName' => 'table',
];
$db->WriteRecords($query);
I dont understand what am I doing wrong here, and the lack of documentations and samples is making it even more difficult to find out!
Thanks for any advice!
In Timestream, the dimensions together with the time are a "key" for upserting. If you have different dimensions, it will insert a new record with the new dimensions.
The version field is only used if all dimensions and time are exactly the same. Then, the measures will be updated with the new values.
You can find better information here: https://docs.aws.amazon.com/timestream/latest/developerguide/data-modeling.html#data-modeling-dimensionsmeasures, under the "Choosing dimensions", the first bullet point.
I am writing to Timestream a list of dimensions and a list of measureValues but I keep getting this error:
"Message":"measureValues (list) not supported for BOOL, DOUBLE, VARCHAR and BIGINT data types. Please use measureValue to send the data."
Here is my code:
$dimensions= [];
$dimensions[] = [
'Dimensions' => [
[
'DimensionValueType' => 'VARCHAR',
'Name' => 'id',
'Value' => '123456',
],
],
'MeasureValues' => [
[
'Name' => 'remark',
'Type' => 'VARCHAR',
'Value' => 'Some test text',
],
]
];
$query = [
'CommonAttributes' => [
'MeasureName' => 'table_cnt',
'MeasureValue' => 'table_cnt',
'MeasureValueType' => 'VARCHAR',
'Time' => '1651501311000',
'TimeUnit' => 'MILLISECONDS',
'Version' => 1,
],
'DatabaseName' => 'mydb',
'Records' => $dimensions,
'TableName' => 'table',
];
$db->WriteRecords($query);
According to AWS documentation here (Parameter Syntax) it clearly shows that the supported data types are "DOUBLE|BIGINT|VARCHAR|BOOLEAN|TIMESTAMP|MULTI". If you check a bit down below under "MeasureValues" bulletpoint, it says the opposite: "This is only allowed for type MULTI." . Eitherway, I did try to change the type to MULTI but it still throws the same error.
As you're expecting to use the format
[
'Name' => 'remark',
'Type' => 'VARCHAR',
'Value' => 'Some test text',
],
as input to measures, you need to declare the MeasureValueType as 'MULTI' and not send a MeasureValue on the body of the request. In your example, the final request would be like this:
$dimensions= [];
$dimensions[] = [
'Dimensions' => [
[
'DimensionValueType' => 'VARCHAR',
'Name' => 'id',
'Value' => '123456',
],
],
'MeasureValues' => [
[
'Name' => 'remark',
'Type' => 'VARCHAR',
'Value' => 'Some test text',
],
]
];
$query = [
'CommonAttributes' => [
'MeasureName' => 'table_cnt',
// Removed MeasureValue from here as it's MULTI
'MeasureValueType' => 'MULTI', // <- changed from 'VARCHAR' to 'MULTI'
'Time' => '1651501311000',
'TimeUnit' => 'MILLISECONDS',
'Version' => 1,
],
'DatabaseName' => 'mydb',
'Records' => $dimensions,
'TableName' => 'table',
];
$db->WriteRecords($query);
As a reference, I would suggest you to try it first without the CommonAttributes, as you're inserting only one record, like I demonstrate on this article: https://du7.medium.com/aws-timestream-multi-measures-71b41c089af4
This is my array
[
'field_test1' => [
'field_test2' => [ 'value' => 'Yes' ,'action' => 'visible']
],
'field_test3' => [
'field_test4' => [ 'value' => '2' ,'action' => 'visible']
]
'body' => [
'field_test2' => [ 'value' => 'No', 'action' => 'visible']
'field_test4' => [ 'value' => '1', 'action' => 'visible']
]
]
When i try to loop through each element i am getting error like invalid argument passed for foreach;
My code is
foreach ($myArray as $key => $value) {
echo $key;
}
what should i do??
You forgot the comma after your second array within your array. Before the one with the 'body' key. Try using a decent IDE like PhpStorm, it will highlight the errors in your syntax for you, making the search for common errors easy.
$myArray =
[
'field_test1' => [
'field_test2' => [ 'value' => 'Yes' ,'action' => 'visible']
],
'field_test3' => [
'field_test4' => [ 'value' => '2' ,'action' => 'visible']
],
'body' => [
'field_test2' => [ 'value' => 'No', 'action' => 'visible']
'field_test4' => [ 'value' => '1', 'action' => 'visible']
],
];
$menus = [
0 => [
'id' => 'home',
'title' => 'Home',
'url' => '/display/home',
'children' => [],
'parent' => null
],
1 => [
'id' => 'nodes',
'title' => 'Nodes',
'url' => 'nodes/index',
'children' => [
0 => [
'id' => 'addNode',
'title' => 'Add Node',
'url' => '/nodes/add',
'children' => [],
'parent' => "nodes"
],
1 => [
'id' => 'editNode',
'title' => 'Edit Node',
'url' => '/nodes/edit',
'children' => [],
'parent' => 'nodes'
],
2 => [
'id' => 'deleteNode',
'title' => 'Delete Node',
'url' => '/nodes/delete',
'children' => [
0 => [
'id' => 'deleteMultipleNodes',
'title' => 'Delete Multiple Nodes',
'url' => '/nodes/deleteall',
'children' => [
0 => [
'id' => 'deleteMultipleSelectedNodes',
'title' => 'Delete Multiple Selected Nodes',
'url' => '/nodes/deleteallselected',
'children' => [],
'parent' => 'deleteMultipleNodes'
]
],
'parent' => 'deleteNode'
]
],
'parent' => 'nodes'
]
],
'parent' => null
]
];
Assuming I have this array. What i want is to recursively search this array for an "id" and if found push a new children to the children array of that element.
I've tried it via different ways, I've also tried to use RecursiveArrayIterator to traverse the array, but the problem is how can i push value to that index of the array when found while traversing.
For Example here is a code from one of my tries:
private function traverseArray($array)
{
$child = [
'id' => 'deleteMultipleNotSelectedNodes',
'title' => 'Delete Multiple Not Selected Nodes',
'url' => '/nodes/deletenotselected',
'children' => [],
'parent' => 'deleteMultipleNodes'
];
foreach($array as $key=>$value)
{
if(is_array($value))
{
$this->traverseArray($value);
}
if($key == "id" && $value == "deleteMultipleNodes")
{
array_push($array["children"], $child); // This part is confusing me, How to add the child on this index where the id is found.
}
}
}
Any help on how to do such thing in an efficient way would save my days.
Here it's how it would work without using $this and fixing bugs in comparing $value instead assigning anything to value.
Please note the difference with &$array and &$value, which are references, so it would change the original data instead of copying it into new variables.
<?php
$menus = [
0 => [
'id' => 'home',
'title' => 'Home',
'url' => '/display/home',
'children' => [],
'parent' => null
],
1 => [
'id' => 'nodes',
'title' => 'Nodes',
'url' => 'nodes/index',
'children' => [
0 => [
'id' => 'addNode',
'title' => 'Add Node',
'url' => '/nodes/add',
'children' => [],
'parent' => "nodes"
],
1 => [
'id' => 'editNode',
'title' => 'Edit Node',
'url' => '/nodes/edit',
'children' => [],
'parent' => 'nodes'
],
2 => [
'id' => 'deleteNode',
'title' => 'Delete Node',
'url' => '/nodes/delete',
'children' => [
0 => [
'id' => 'deleteMultipleNodes',
'title' => 'Delete Multiple Nodes',
'url' => '/nodes/deleteall',
'children' => [
0 => [
'id' => 'deleteMultipleSelectedNodes',
'title' => 'Delete Multiple Selected Nodes',
'url' => '/nodes/deleteallselected',
'children' => [],
'parent' => 'deleteMultipleNodes'
]
],
'parent' => 'deleteNode'
]
],
'parent' => 'nodes'
]
],
'parent' => null
]
];
function traverseArray(&$array)
{
$child = [
'id' => 'deleteMultipleNotSelectedNodes',
'title' => 'Delete Multiple Not Selected Nodes',
'url' => '/nodes/deletenotselected',
'children' => [],
'parent' => 'deleteMultipleNodes'
];
foreach($array as $key=>&$value)
{
if(is_array($value))
{
traverseArray($value);
}
if($key == "id" && $value == "deleteMultipleNodes")
{
array_push($array["children"], $child);
}
}
}
echo "=== before \n";
var_export($menus);
echo "\n\n";
traverseArray($menus);
echo "=== after \n";
var_export($menus);
I have a CollectionSet<UDT> where UDT contains a CollectionMap<int,boolean>. I have not been able to find any documentation or example of how to define this when creating a new Cassandra\Type\CollectionSet for inserting into the table. There is a great example with a CollectionList (found here) which is like this:
// CollectionSet<UDT>, where UDT contains: Int, Text, Boolean,
// CollectionList<Text>, CollectionList<UDT>
new Cassandra\Type\CollectionSet([
[
'id' => 1,
'name' => 'string',
'active' => true,
'friends' => ['string1', 'string2', 'string3'],
'drinks' => [['qty' => 5, 'brand' => 'Pepsi'], ['qty' => 3, 'brand' => 'Coke']]
],[
'id' => 2,
'name' => 'string',
'active' => false,
'friends' => ['string4', 'string5', 'string6'],
'drinks' => []
]
], [
[
'type' => Cassandra\Type\Base::UDT,
'definition' => [
'id' => Cassandra\Type\Base::INT,
'name' => Cassandra\Type\Base::VARCHAR,
'active' => Cassandra\Type\Base::BOOLEAN,
'friends' => [
'type' => Cassandra\Type\Base::COLLECTION_LIST,
'value' => Cassandra\Type\Base::VARCHAR
],
'drinks' => [
'type' => Cassandra\Type\Base::COLLECTION_LIST,
'value' => [
'type' => Cassandra\Type\Base::UDT,
'typeMap' => [
'qty' => Cassandra\Type\Base::INT,
'brand' => Cassandra\Type\Base::VARCHAR
]
]
]
]
]
]);
I've tried using the above example with several variations to accommodate the CollectionMap but nothing is working. My last attempt was this
new Cassandra\Type\CollectionSet($udt_array, [[
'type'=>Cassandra\Type\Base::UDT,
'definition' => [
'map_name' => [
'type' => Cassandra\Type\Base::COLLECTION_MAP,
'value' => [
Cassandra\Type\Base::INT,
Cassandra\Type\Base::BOOLEAN
]
]
]
]])
which gives the error Caught exception: Since v0.7, collection types should have \"definition\" directive. I've also tried using 'definition' instead of 'value'. I'm running out of ideas, any help would be greatly appreciated.
Use "definition" instead of "value". I tried this before but apparently I was doing something else wrong because this worked.
new Cassandra\Type\CollectionSet($udt_array, [[
'type'=>Cassandra\Type\Base::UDT,
'definition' => [
'map_name' => [
'type' => Cassandra\Type\Base::COLLECTION_MAP,
'definition' => [
Cassandra\Type\Base::INT,
Cassandra\Type\Base::BOOLEAN
]
]
]
]])