如何使用DynamoDB PHP从表中获取最新的时间戳值

时间:2014-01-21 06:00:44

标签: php amazon-web-services amazon-dynamodb

我是DynamoDB的新手 在我的应用程序中,每个注册用户的帐户都有一些传感器,这些传感器每隔5分钟就会向我们的数据库发送一些数据。

现在我想要显示“如果用户已登录他的帐户,我应该显示所有传感器,并为每个传感器显示最新的时间戳值”。

我通过三个查询完成了此操作,例如“我在其帐户下获取了所有设备 - >原始传感器ID - >每个传感器最新值”,因此此过程需要很长时间才能执行。

我的桌子看起来像这样:

用户:

---------------------
|sno  | userId      |
---------------------
| 1   | naveenkumar |
|--------------------
| 2   | abc         |
|--------------------
| 3   | xyz         |
|--------------------

sensor_devices:

---------------------
| id | sensorId     |
---------------------
| 1  | sensor1      |
|--------------------
| 2  | sensor2      |
|--------------------
| 3  | sensor3      |
|--------------------
| 4  | sensor4      |
---------------------
| 5  | sensor5      |
---------------------

并且

用户的传感器:

----------------------
| userId | sensorId  |
----------------------
| 1      |  1        |
|---------------------
| 1      |  2        |
|---------------------
| 1      |  4        |
|---------------------
| 2      |  5        |
|---------------------

data_tbl:

---------------------------------------------
| 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>";
?>

如果我能得到答案,我会完成我的工作。 感谢

1 个答案:

答案 0 :(得分:7)

从关系数据库的角度来看,您正在研究和思考DynamoDB。 DynamoDB 关系数据库。您(通常)不希望像在MySQL中那样在DynamoDB中建模您的数据。就像软件开发/计算机科学中的任何事情一样,这是一种权衡。您需要支付一些数据去规范化和重复成本,以换取极低的查询延迟和极高的可扩展性。

我不使用PHP,因此我无法帮助您处理代码,但我认为我可以帮助您完成数据模型设计。

如果我正确理解您的要求,则需要在用户登录时获取每个用户的传感器ID列表及其最新时间戳。如果是这样,这里有一种可能的方法可以将您的查询从3减少到1:

您的表的哈希键为UserID,范围键为传感器事件的Timestamp

------------------------
| Hash Key | Range Key |
------------------------
| User ID  | Timestamp |
------------------------

该表的属性为Sensor ID,对应于哪个传感器观察到该事件。传感器12在2014年2月14日上午11:51观察到的用户29的条目可能如下所示:

---------------------------------------
| Hash Key | Range Key     | Sensor ID |
----------------------------------------
|    12    | 1392396884000 |    29     |
----------------------------------------

请注意,我使用时间戳(以毫秒为单位),以便DynamoDB可以轻松对其进行排序。

现在,当用户登录时,您可以通过User 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会自动将其投影到索引中。

希望有所帮助。