LoginSignup
17
14

More than 5 years have passed since last update.

DynamoDBを簡単に操作するためのインターフェース Kettle/ORMの紹介

Last updated at Posted at 2014-06-03

はじめに

DynamoDBにも、AWS SDK for PHPは提供されているのですが、どうも使いにくいです。
というのも、検索や更新のパラメータや取得したデータのフォーマットが配列で、
すべて微妙に違うので覚えられない。つらい。ということで作りました。

使い方イメージ

ユーザーID 10番の人のデータを取得し、名前を John に更新する例

<?php
use Kettle\ORM;

$user = ORM::factory('User')->findOne(10);
$user->name = 'John';
$user->save();

ユーザーID 10番の人のつぶやきをすべて取得して出力する例

<?php
use Kettle\ORM;

$tweets = ORM::factory('Tweet')->where('user_id', 10)
                 ->findMany();

foreach ($tweets as $tweet) {
    echo $tweet->text . PHP_EOL;
}

こんな感じに、あまりDynamoDBを意識せずにObjectを操作する感覚で扱えます。

インストール

composer からインストールできます。

composer.json

{
    "require": {
        "kettle/dynamodb-orm": "dev-master"
    }
}
  1. 上記のようなファイルを composer.json というファイル名で保存。
  2. 下記のコマンドを実行してインストールします。 composer.phar は別途インストールしてください。
$ composer.phar install

vendor 以下にインストールされます。
使うに際には、autoload.php をrequireしておけばクラス使用時に自動的にロードされるようになります。

<?php

require_once __DIR__.’/vendor/autoload.php’;

使い方

1. まずは設定

下記のような形で AWSの認証情報をセットします。

<?php
use Kettle\ORM;

ORM::configure("key",    YOUR_AWS_KEY');
ORM::configure("secret", ‘YOUR_AWS_SECRET');
ORM::configure("region", YOUR_AWS_REGION');

// DynamoDB Localを使うには、base_url をセットします。
ORM::configure("base_url", ‘http://localhost:8000');

2. 次にテーブルに対応するEntityクラスを作成します。

実際に上記使い方イメージのように操作するには Userクラス、Tweetクラスが必要です。
ORMを継承したクラスに、テーブル名、ハッシュキー、レンジキー、カラムを定義します。

<?php

use Kettle\ORM;

class User extends ORM {
    protected $_table_name = 'user';
    protected $_hash_key   = 'user_id';
    protected $_schema = array(
      'user_id'    => 'N',  // user_id is number
      'name'       => 'S',  // name is string
      'age'        => 'N',
      'country'    => 'S',
     );
}

class Tweets extends ORM {
    protected $_table_name = tweets;
    protected $_hash_key   = 'user_id';
    protected $_range_key  = timestamp;

    protected $_schema = array(
      'user_id'    => 'N',  
      timestamp  => 'S', 
      text       => S,
      is_deleted => N,
     );
}

DynamoDBはスキーマレスなので、定義とか必要なくなんでも突っ込めるのですが、
コードをメンテナンスする際に、データに何が入っているか把握できないと保守性が下がるため
上記のように定義しておく形を取っています。

Userクラスを使用する際には、次のようにfactoryメソッドを使いインスタンスを生成します。

<?php

$user = ORM::factory('User);

3. データ操作(データの登録)

  1. create メソッドで空のインスタンスを作成
  2. 値を代入
  3. save()
<?php

$user = ORM::factory('User')->create();
$user->id = 1;
$user->name = 'John';
$user->age  = 20;
$user->save();

4. データの操作(1レコードの取得)

  1. findOne にHashKeyの値を指定します。
<?php

$user = ORM::factory('User')->findOne(1);
echo $user->name. PHP_EOL;

// asArray() で連想配列になります。
print_r($user->asArray());

HashKeyとRangeKeyからなるテーブルの場合は両方を渡します。

$hoge = ORM::factory(‘Hoge’)->findOne(1, ‘fuga’);

5. データの操作(更新)

  1. findOneでデータを取得します。
  2. 新しいデータをセットします。
  3. save()
<?php

$user = ORM::factory('User')->findOne(1);
$user->age = 21;
$user->save();

6. データの操作(検索)

注意:
DynamoDBでは、インデックスを張ったカラムでしか検索ができません。
HashKey, RangeKey、Local Secondary Index、Global Secondary Index
などを事前に作成しておく必要があります。

  1. whereメソッドを使い条件を指定します。
  2. findMany で取得します。
<?php

$tweets = ORM::factory('Tweets')
        ->where('user_id', 1)
        ->where('timestamp', '>', 1397264554)
        ->findMany();

foreach ($tweets as $tweet) {
     echo $tweet->text . PHP_EOL;
}

  • whereメソッドは、引数が2つの時には、第1引数がkey名、第2引数が値になり、完全一致の検索となります。
  • 引数が3つの場合には、第1引数がkey名、第2引数が比較演算子、第3引数が値となります。
  • 比較演算子は、”=“, “<=“, “>“, “BETWEEN” などの一般的なものが使えます。

7. データの操作(GSIを使った検索)

Global Secondary Index を使って検索するには、下記のように
index() メソッドでインデックス名を指定します。

<?php

$users = ORM::factory('User')
        ->where('country', 'Japan')
        ->where('age', '>=', 20)
        ->index('country-age-index')  // インデックス名を指定
        ->findMany();

8. データの操作(検索+クエリフィルタリング)

前述のとおり、DynamoDBはインデクスを指定した検索しかすることができませんが、
クエリフィルタリングという形で、検索した結果をフィルタして取得することができます。

下記の例は、is_deleted が 0 のものだけに絞って取得しています。

<?php

$tweets = ORM::factory('Tweets')
          ->where('user_id', 1)
          ->filter('is_deleted', 0) // using filter
          ->findMany();

進んだ使い方

1. シーケンスを管理するテーブルを作る

DynamoDBでは、MySQLのauto_incrementのように自動でカウントアップするカラムは作れませんが、工夫でauto_increment的な動きをするカラムを作ることができます。

sequence というテーブルを作っておきます。
HashKey は name (S) です。

<?php

use Kettle\ORM;

class Sequence extends ORM
{
    protected $_table_name = "sequence";
    protected $_hash_key   = "name";

    protected $_schema = array(
        'name'  => 'S',
        'count' => 'N',
    );

    public function getNextId($name)
    {
        $this->name = $name;
        $values  = ['count' => 1];
        $options = ['Action' => ['count' => 'ADD'], 'ReturnValues' => 'UPDATED_NEW'];
        $result = $this->updateItem($values, $options);
        $count = $result->getPath('Attributes/count/N');
        return $count;
    }
}

こんなクラスを作っておいて、

<?php

$user_id = ORM::factory('Sequence')->getNextId('user_id');
var_dump($user_id);

こんな感じで新しいIDを取り出します。何度も呼び出すとカウントアップされているのが分かります。

user_id の部分は、任意の文字列でOKです。

おわりに

バグ等ありましたら Githubの方に報告をお願いします。
https://github.com/inouet/kettle

17
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
14