Laravel+AWS-SDK-PHP로 DynamoDB 데이터 획득

배경



Laravel에서 DynamoDB를 사용할 때 ORM의 laravel-dynamodb 등도 있지만 DynamoDB에서 ORM을 사용하는 것이 조금 위화감 있었기 때문에 SDK를 사용해 보았을 때의 메모 그렇지만 모처럼 SDK가 제공되고 있으므로 한번 사용해 보자는 느낌)

환경



· Windows 10
· HomeStead 9.5
· PHP 7.4
・Laravel 6.0

1. 준비



AWS-SDK-PHP 설치


composer require aws/aws-sdk-php

DynamoDB 환경 만들기



AWS 제공 로컬 DynamoDB를 이용. Vagrant를 사용했기 때문에 Docker와 공존이 번거롭기 때문에 로컬에 직접 설치했습니다.
htps : // / cs. 아 ws. 아마존. 이 m / 그럼 _ jp / 아마 젠 dy 나도 db / ㅁ st / ゔ ぇぺぺ ぐ い / Dy 이나 DB ㄉ인가 l. HTML

※GUI 툴(상당히 편리)
htps : // / cs. 아 ws. 아마존. 이 m / 그럼 _ jp / 아마 젠 dy 나도 db / ㅁ st / ゔ ぇ ぺ ぺ ぐ い /를 rk 벤 ch. 싱싱 p. HTML

DynamoDB 시작


java -Djava.library.path=C:\localsandbox\DynamoDB\DynamoDBLocal_lib -jar C:\localsandbox\DynamoDB\DynamoDBLocal.jar -port 8001 -sharedDb

※Homestead의 VirtualBox와 초기 포트 8000이 쓰이므로, 8001로 기동시킨다

테스트용 테이블 만들기



테이블 이름: SensorLog
파티션 키: device_id
정렬 키: receive_dt
aws dynamodb create-table --table-name SensorLog --attribute-definitions AttributeName=device_id,AttributeType=S AttributeName=receive_dt,AttributeType=N --key-schema AttributeName=device_id,KeyType=HASH AttributeName=receive_dt,KeyType=RANGE --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 --endpoint-url http://localhost:8001 

※키가 없는 항목은 테이블 작성시에 지정할 수 없기 때문에, 테스트 데이터 작성시에 적당하게 만든다.
※테스트 데이터는 GUI로 적당하게 작성

.env에 정보 설정


DYNAMODB_REGION=ap-northeast-1
#↓vagrantのlocalhost:xxxxだとつながらないのでローカルIPを設定
DYNAMODB_LOCAL_ENDPOINT=http://192.168.11.99:8001
DYNAMODB_DEBUG=true

2. 데이터 획득



・파티션 키로 짜서 데이터 검색한 결과의 최신을 취득한다.
· 파티션 키 + 정렬 키 (범위 지정)로 복합 조건 검색 결과 목록을 얻습니다.
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
use Aws\Sdk as AwsSdk;

class SensorLog
{
    /**
     * @var DynamoDbClient
     */
    private $client;

    /**
     * @var Marshaler
     */
    private $marshaler;

    /**
     * DynamoModel constructor.
     */
    public function __construct()
    {
        // ローカルDBであっても"credentials"定義しないとエラーが吐かれるので注意
        $sdk = new AwsSdk([
            'credentials' => [
                'key' => env('DYNAMODB_KEY'),
                'secret' => env('DYNAMODB_SECRET'),
            ],
            'endpoint'   => env("DYNAMODB_LOCAL_ENDPOINT"),
            'region'   => env("DYNAMODB_REGION"),
            'version'  => 'latest'
        ]);

        $this->client = $sdk->createDynamoDb();
        $this->marshaler = new Marshaler();
    }

    /**
     * パーティションキー指定による最新データを取得する
     */
    public function getFirst($id)
    {
        $tableName = 'SensorLog';

        // 検索条件設定:device_idを検索条件にする
        $key_value = $id;
        $jsonStr = '{'.'":device_id":'.'"'.$key_value.'"'.'}';
        $eav = $this->marshaler->marshalJson($jsonStr);

        // Limit:1 取得件数を1件に制限
        // ScanIndexForward:false ソートキー(receive_dt)を降順指定
        $params = [
            'TableName' => $tableName,
            'KeyConditionExpression' => '#id = :device_id',
            'ExpressionAttributeNames'=> [ '#id' => 'device_id' ],
            'Limit' => 1,
            'ScanIndexForward' => false,
            'ExpressionAttributeValues'=> $eav,
        ];

        try {
            $result = $this->client->query($params);
            $data = array();
            foreach ($result['Items'] as $recdData) {
                $data[] =  $this->marshaler->unmarshalItem($recdData);
            }
            return $data;
        } catch (DynamoDbException $e) {
            throw $e;
        }
    }

    /**
     * パーティションキー+対象日付のデータリストを取得する
     */
    public function getDataByDateTime(int $id, string $dt)
    {
        $tableName = 'SensorLog';

        // 対象日付の最小時間と最大時間を設定する
        // receive_dt:YYYYMMDDHHMMSSの値は数値型で格納されている
        $from_dt = $dt."000000";
        $to_dt = $dt."235959";

        // バインド変数を設定(device_id,from_dt,to_dt)
        $key_value = $id;
        $jsonStr = '{' . '":device_id":' . '"' .$key_value.'",":from_dt":'.$from_dt.',":to_dt":'.$to_dt.'}';
        $eav = $this->marshaler->marshalJson($jsonStr);

        // device_idとreceive_dtによる範囲検索を行う
        // ScanIndexForward:false ソートキー(receive_dt)を降順指定
        $params = [
            'TableName' => $tableName,
            'KeyConditionExpression' => '#id = :device_id and receive_dt between :from_dt and :to_dt',
            'ExpressionAttributeNames'=> [ '#id' => 'device_id' ],
            'ScanIndexForward' => false,
            'ExpressionAttributeValues'=> $eav,
        ];

        try {
            $result = $this->client->query($params);
            $data = array();
            foreach ($result['Items'] as $recdData) {
                $data[] =  $this->marshaler->unmarshalItem($recdData);
            }
            return $data;
        } catch (DynamoDbException $e) {
            throw $e;
        }
    }
}

전화



· 컨트롤러로 호출
//1.指定IDの最新データを1件取得
$sensorLog = $sensor->getFirst($id);
//2.2020-08-06のデータを検索して結果リストを取得
$sensorLogList = $sensor->getDataByDateTime($id, "20200806");
dump($sensorLogList);

· 결과


참고

좋은 웹페이지 즐겨찾기