2014-01-21 62 views
2

我是DynamoDB的新手。
在我的應用程序中,每個註冊用戶在他的賬戶上都有一些傳感器,這些傳感器會每隔5分鐘向我們的數據庫發送一些數據。如何使用DynamoDB從表中獲取最新的時間戳值PHP

現在我想顯示「如果用戶已經登錄到他的帳戶,我應該需要顯示所有他的傳感器與每個傳感器的最新時間戳值」。

我這樣做了三個查詢,例如「我提取了他的賬戶下的所有設備 - >原始傳感器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>"; 
?> 

如果我能得到答案,我會完成我的工作。 謝謝

回答

6

您從關係數據庫的角度看待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可以很容易地對其進行排序。

現在,當用戶登錄時,您可以通過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會自動將其投影到索引中。

希望有所幫助。

相關問題