我是 DynamoDB 的新手。
在我的应用程序中,每个注册用户的帐户上都有一些传感器,这些传感器每 5 分钟就会向我们的数据库发送一些数据。
现在我想显示“如果用户已登录到他的帐户,我应该需要显示他的所有传感器以及每个传感器的最新时间戳值”。
我通过三个查询来完成此操作,例如“我获取了他帐户下的所有设备 -> 原始传感器 ID -> 每个传感器的最新值”,因此执行此过程需要很长时间。
我的表格是这样的:
用户:
---------------------
|sno | userId |
---------------------
| 1 | naveenkumar |
|--------------------
| 2 | abc |
|--------------------
| 3 | xyz |
|--------------------
传感器设备:
---------------------
| id | sensorId |
---------------------
| 1 | sensor1 |
|--------------------
| 2 | sensor2 |
|--------------------
| 3 | sensor3 |
|--------------------
| 4 | sensor4 |
---------------------
| 5 | sensor5 |
---------------------
和
用户传感器:
----------------------
| userId | sensorId |
----------------------
| 1 | 1 |
|---------------------
| 1 | 2 |
|---------------------
| 1 | 4 |
|---------------------
| 2 | 5 |
|---------------------
数据表:
---------------------------------------------
| sensorId | value | timestamp |
---------------------------------------------
| sensor1 | 4.3 | 2014-01-21 11:21:00|
|--------------------------------------------
| sensor2 | 5.0 | 2014-01-21 11:22:00|
|--------------------------------------------
| sensor3 | 10.0 | 2014-01-21 11:19:00|
|--------------------------------------------
| sensor4 | 6.3 | 2014-01-21 11:25:00|
|--------------------------------------------
| sensor1 | 8.3 | 2014-01-21 11:26:00|
|--------------------------------------------
| sensor2 | 6.0 | 2014-01-21 11:27:00|
|--------------------------------------------
| sensor3 | 9.0 | 2014-01-21 11:24:00|
|--------------------------------------------
| sensor4 | 6.3 | 2014-01-21 11:30:00|
|--------------------------------------------
最终输出表将在他的主页上看到用户:
---------------------------------------------
| sensorId | value | timestamp |
---------------------------------------------
| sensor1 | 8.3 | 2014-01-21 11:26:00|
|--------------------------------------------
| sensor2 | 6.0 | 2014-01-21 11:27:00|
|--------------------------------------------
| sensor4 | 6.3 | 2014-01-21 11:30:00|
|--------------------------------------------
我的查询看起来像这样,执行起来需要很长时间,所以请为我提供更好的解决方案:
让我们假设 $_SESSION['login_id'] = 1;
<?php
$aws = Aws::factory('config.php');
$client = $aws->get("dynamodb");
$tableName = "data_tbl";
echo "<table border=1>";
echo "<tr>";
echo "<th>Sensor ID</th>";
echo "<th>value</th>";
echo "<th>Timestamp</th>";
echo "</tr>";
//Query to get user devices
$devices = $client->query(array(
"TableName" => "users-sensors",
"KeyConditions" => array(
"userId" => array(
"ComparisonOperator" => ComparisonOperator::EQ,
"AttributeValueList" => array(
array(Type::STRING => $_SESSION['login_id'])
)
)
)
));
foreach ($devices['Items'] AS $key=>$value) {
$id = $value['sensorId']['S'];
//Query to get original sensorId from sensor serial number
$device = $client->query(array(
"TableName" => "sensor_devices",
"KeyConditions" => array(
"id" => array(
"ComparisonOperator" => ComparisonOperator::EQ,
"AttributeValueList" => array(
array(Type::STRING => $id)
)
)
)
));
$dids = $device['Items'][0]['sensorId'][Type::STRING];
//Query to get all latest values of sensors
$response = $client->query(array(
"TableName" => $tableName,
"KeyConditions" => array(
"sensorId" => array(
"ComparisonOperator" => ComparisonOperator::EQ,
"AttributeValueList" => array(
array(Type::STRING => $dids)
)
)
),
"Select" => "SPECIFIC_ATTRIBUTES",
"AttributesToGet" => array("sensorId","value","timestamp"),
"ScanIndexForward" => false,
"Limit" => 1
));
foreach ($response['Items'] AS $key=>$value) {
echo "<tr>";
$link = "graph.php?id=".$id;
echo "<td><a href='$link'>".$value['sensorId']['S']."</a></td>";
echo "<td><a href='$link'>".$value['value']['S']."</a></td>";
$epoch = $value['timestamp']['S'];
$timestamp = date('Y-m-d H:i:s', $epoch);
echo "<td><a href='$link'>".$timestamp."</a></td>";
echo "</tr>";
}
}
echo "</table>";
?>
如果我能得到答案,我就能完成我的工作。 谢谢
最佳答案
您正在从关系数据库的角度看待和思考 DynamoDB。 DynamoDB 不是关系数据库。您(通常)不想像在 MySQL 中那样在 DynamoDB 中对数据建模。就像软件开发/计算机科学中的任何事情一样,这是一种权衡。您支付一些数据反规范化和复制成本,以换取极低的查询延迟和极强的可扩展性。
我不使用 PHP,所以我无法帮助您编写代码,但我想我可以帮助您设计数据模型。
如果我正确理解您的要求,则需要在用户登录时获取每个用户的传感器 ID 列表及其最新时间戳。如果是这样,您可以采用以下一种可能的方法将查询次数从 3 次减少到 1 次:
您表的哈希键是 UserID
,范围键是传感器事件的 Timestamp
:
------------------------
| Hash Key | Range Key |
------------------------
| User ID | Timestamp |
------------------------
该表将具有 Sensor ID
属性,对应于观察到事件的传感器。传感器 29
于 2014 年 2 月 14 日上午 11:51 观察到的用户 12
的条目可能如下所示:
---------------------------------------
| Hash Key | Range Key | Sensor ID |
----------------------------------------
| 12 | 1392396884000 | 29 |
----------------------------------------
请注意,我使用了以毫秒为单位的时间戳,以便 DynamoDB 可以轻松地对其进行排序。
现在,当用户登录时,您可以通过用户 ID
查询表以获取该用户的每个事件。在您的查询请求中,设置 ScanIndexForward => false
(来自此处的 DynamoDBSDK 文档:http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.DynamoDb.DynamoDbClient.html#_query)。 DynamoDB 将按从最近到最不最近的顺序返回您的结果。如果该用户有大量事件,DynamoDB 将相应地对结果集进行分页,但您可以在 DynamoDB 文档中了解如何处理。
现在您有了该用户的事件列表(或 PHP 中的任何相应数据结构)。您需要按 SensorID
进行过滤以获取最新的。好消息是,由于结果是有序的,您只需遍历结果并检查每个项目的 Sensor ID
;如果您没有从该 Sensor ID
获得结果,请将其添加到您的过滤集合中。如果您已经从该 Sensor ID
添加了一个事件,则意味着您拥有来自该 Sensor ID
的该 User ID
的最新事件你应该跳过它。
根据您的应用程序的需要,如果您需要获取传感器的每个事件的列表,您可以简单地使用 Sensor ID
的索引散列键在表上放置一个全局二级索引> 和事件 Timestamp
。由于 User ID
是表主键的一部分,DynamoDB 会自动将其投影到索引中。
希望对您有所帮助。
关于php - 如何使用 DynamoDB PHP 从表中获取最新的时间戳值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21250308/