DynamoDB PHP Sample Codes
AWS 工具組功能強大,而且功能還以火箭速度不斷開發,每年 AWS 的研發支出還力壓 Google。 不過要說 AWS 缺點的話也不是沒有…
一個是它是 Amazon WEB Service, 所以沒有網路的話就完全無用,這聽來是癈話,但是在 IoT 應用方面卻是一大問題,因為 IoT Device 的網路連線不可能是 100% 暢通的。所以 Greengrass 技術是十分重要的…. 我期待Greengrass 技術繼續發展下去。
另一個缺點是,因為功能出得太快太新了,線上文件也不是很好看,而且因為 AWS 同時支援數個語言,像是 DynamoDB 就有 Java 、JavaScript 、Node.js、.NET、PHP、Python、Ruby,還有iOS SDK、 Android SDK …等。
支援的程式語言很多是好事,但是也引發了一個問題:要嘛很難查到線上範例,要嘛勉強查到的範例卻不是自己使用的語言,雖然可以參考但是還是不是那麼方便。我自己就有無數次到 Stack Overflow 去查問題,結果要嘛只查到問題無人回答,要嘛竟然連問題都沒有的情況。
在這裡分享許多我用過的 PHP example codes,對於要使用 PHP 撰寫 DynamoDB 程式的開發者應該多少會有點幫助:
AWS helper function
function array_from_aws_result($awsArray)
{
$data_table = array();
foreach($awsArray as $k => $v){
if(array_key_exists('S',$v)){
$data_table[$k]=$v['S'];
}
if(array_key_exists('N',$v)){
$data_table[$k]=floatval($v['N']);
}
}
return $data_table;
}
Scan all records
do{
$request = [
'TableName' => 'IotecUser'
];
if(isset($result) && isset($result['LastEvaluatedKey'])) {
$request['ExclusiveStartKey'] = $result['LastEvaluatedKey'];
}
$result = $dynamoDbClient -> scan($request);
foreach ($result['Items'] as $record) {
$list_table = array_from_aws_result($record);
}
}while(isset($result['LastEvaluatedKey']));
if(count($list_table) != 0){
// process the list table
}else{
// record not found
}
Scan table using query index. Single attribute index.
Partition Key: s_deviceId
Paramter: $deviceId
do{
$request = [
'TableName' => 'DeviceList',
'IndexName' => 's_deviceId-index',
'KeyConditionExpression' => 's_deviceId = :v_deviceId ',
'ExpressionAttributeValues' =>
[
':v_deviceId' => ['S' => $deviceId]
]
];
if(isset($result) && isset($result['LastEvaluatedKey'])) {
$request['ExclusiveStartKey'] = $result['LastEvaluatedKey'];
}
$result = $dynamoDbClient -> query($request);
foreach ($result['Items'] as $record) {
$list_table = array_from_aws_result($record);
}
}while(isset($result['LastEvaluatedKey']));
if(count($list_table) != 0){
// process the list table
}else{
// record not found
}
Scan table using query index. Double attributes index.
Partition Key: n_certified
do{
$request = [
'TableName' => 'IotecPost',
'IndexName' => 'n_certified-n_view_count-index',
'KeyConditionExpression' => 'n_certified = :v_certified ',
'ScanIndexForward' => false, // switch forward or backward
'FilterExpression' => 's_country_code = :v_country_code',
'ExpressionAttributeValues' =>
[
':v_certified' => ['N' => '1'],
':v_country_code' => ['S' => 'TW']
]
];
if(isset($result) && isset($result['LastEvaluatedKey'])) {
$request['ExclusiveStartKey'] = $result['LastEvaluatedKey'];
}
$result = $dynamoDbClient -> query($request);
$list_table[] = array();
foreach ($result['Items'] as $record) {
$item_table = array();
foreach($record as $k=>$v){
if(array_key_exists('S',$v)){
$item_table[$k]=$v['S'];
}
if(array_key_exists('N',$v)){
$item_table[$k]=floatval($v['N']);
}
}
$list_table[] = $item_table;
}
// if LastEvaluatedKey is set, means this is no the last record. Continue next query
}while(isset($result['LastEvaluatedKey']));
if(count($list_table) != 0){
// process the list table
}else{
// record not found
}
Get a dedicate record using getItem with Partition key.
Partition key: n_post_sn
$result = $dynamoDbClient->getItem(array(
'ConsistentRead' => true,
'TableName' => 'IotecPost',
'Key' => array(
'n_post_sn' => array('N' => '')
)
));
$postTable = array_from_aws_result($result['Item']);
var_dump($postTable);
Get a dedicate record using getItem with Partition key and sort key.
Partition key: n_post_sn
Sort key: s_email
$result = $dynamoDbClient->getItem(array(
'ConsistentRead' => true,
'TableName' => 'IotecPost',
'Key' => array(
's_email' => array('S' => ''.$s_email),
'n_post_sn' => array('N' => ''.$n_post_sn)
)
));
Update record with updateItem
Partition key: n_post_sn
Sort key: s_email
Parameter: $userEmail,$postSn, $attributeName, $attributeType, $attributeValue
$dynamoDbClient->updateItem(array(
'TableName' => 'IotecPost',
'Key' => array(
's_email' => array('S' => ''.$userEmail),
'n_post_sn' => array('N' => ''.$postSn)
),
"UpdateExpression" => "SET #key = :val",
"ExpressionAttributeNames" => ['#key' => $attributeName],
"ExpressionAttributeValues" => [':val' => [$attributeType => ''.$attributeValue]]
));
Delete record with deleteItem
Partition key: n_post_sn
Sort key: s_email
Parameter: $userEmail,$postSn
$dynamoDbClient->deleteItem(array(
'TableName' => 'IotecPost',
'Key' => array(
's_email' => array('S' => ''.$userEmail),
'n_post_sn' => array('N' => ''.$postSn)
)
));
Remove attribute
Partition key: n_post_sn
Sort key: s_email
Parameter: $userEmail,$postSn
$result = $dynamoDbClient->updateItem(array(
'TableName' => 'IotecPost',
'Key' => array(
's_email' => array('S' => ''.$userEmail),
'n_post_sn' => array('N' => ''.$postSn)
),
"UpdateExpression" => "REMOVE s_address2"
));
DynamoDB PHP 最常見的坑
參數不接受空字串!參數不接受空字串!參數不接受空字串!
因為太重要了,要重覆三次
舉例如下:
Partition key: s_email
Parameter: $userName, $userEmail
$dynamoDbClient->updateItem(array(
'TableName' => 'IotecUser',
'Key' => array(
's_email' => array('S' => ''.$userEmail)
),
"UpdateExpression" => "SET #key = :val",
"ExpressionAttributeNames" => ['#key' => 's_name'],
"ExpressionAttributeValues" => [':val' => ['S' => ''.$userName]]
));
上面的 code, 在 $userName = ” 的情況下,會發生錯誤
… One or more parameter values were invalid: An AttributeValue may not contain an empty string …
只要看到上述這個錯誤訊息,八成又發生某個參數是空字串了
Bookmarked!, I love it!