aiotu/terseq

AWS DynamoDB 查询构建器

v0.1.2 2024-09-24 16:19 UTC

This package is auto-updated.

Last update: 2024-09-24 16:20:03 UTC


README

codecov

本文件提供了如何利用 Terseq 库使用 AWS SDK for PHP 构建 AWS DynamoDB 查询的全面指南。

功能

Terseq 支持构建以下 DynamoDB 操作的查询

单项操作

查询操作

事务

批量

为什么我应该使用这个库?

AWS SDK for PHP 是处理 AWS 服务的强大工具,但由于其复杂性,使用起来可能会有些挑战。它需要编写大量模板代码来构建和执行查询。Terseq 通过提供构建 DynamoDB 操作查询的流畅接口来简化这一过程。它还支持单表设计,这是 DynamoDB 的推荐做法。

安装

要安装 Terseq 包,请使用 Composer 在您的项目目录中运行以下命令

composer require aiotu/terseq

使用方法

初始化

通过 AWS SDK 和 DatabaseManager 创建客户端

$client = new \Aws\DynamoDb\DynamoDbClient([
    'region' => 'us-west-2',
    'version' => 'latest',
]);

$manager = new \Terseq\DatabaseManager($client, new Marshaler());

操作

GetItem

$manager->getItem()
    ->table(['Books', 'BookId'])
    ->pk('super-cool-id')
    ->dispatch();

PutItem

$manager->putItem()
    ->table(['Books', 'BookId'])
    ->item([
        'BookId' => 'super-cool-id',
        'Title' => 'Super Cool Book',
        'Author' => 'Super Cool Author',
    ])
    ->dispatch();

UpdateItem

$manager->updateItem()
    ->table(['Books', 'BookId'])
    ->pk('super-cool-id')
    ->set('Title', 'Super Cool Book Updated')
    ->set('Author', 'Super Cool Author Updated')
    ->dispatch();

DeleteItem

$manager->deleteItem()
    ->table(['Books', 'BookId'])
    ->pk('super-cool-id')
    ->dispatch();

Query

$result = $manager->query()
    ->table(['Books', 'BookId'])
    ->pk('super-cool-id')
    ->consistentRead()
    ->disaptch();

TransactGetItems

use Terseq\Builders\Operations\TransactGetItems\Operations\Get;

$manager->transactGetItems()
    ->get(
            [
                static fn (Get $get) => $get->pk('super-cool-id1'),
                static fn (Get $get) => $get->pk('super-cool-id2'),
            ], 
            table: ['Books', 'BookId'],
        )
    ->dispatch();

TransactWriteItems

use Terseq\Builders\Operations\TransactWriteItems\Operations\Delete;
use Terseq\Builders\Operations\TransactWriteItems\Operations\Put;
use Terseq\Builders\Operations\TransactWriteItems\Operations\Update;

$manager->transactWriteItems()
    ->put(
        [
            fn (Put $put) => $put->item([
                'BookId' => 'super-book1',
                'Author' => 'Unknown',
            ]),
            fn (Put $put) => $put->item([
                'BookId' => 'super-book-2',
                'Author' => 'Incognito',
            ]),
        ],
        table: ['Books', 'BookId'],
    )
    ->update(
        fn (Update $update) => $update
            ->pk('super-book-3')
            ->set('Author', 'Incognito'),
        table: ['Books', 'BookId'],
    )
    ->delete(
        fn (Delete $delete) => $delete->pk('super-book-4'),
        table: ['Books', 'BookId'],
    )
    ->dispatch();

BatchGetItem

$manager->batchGetItem()
    ->get(
        [
            'BookId' => 'super-book-1',
            'Author' => 'Unknown',
        ],
        table: ['Books', 'BookId'],
    )
    ->get(
        [
            'BookId' => 'super-book-2',
            'Author' => 'Incognito',
        ],
        table: ['Books', 'BookId'],
    )
    ->dispatch();

BatchWriteItem

$manager->batchWriteItem()
    ->put(
        [
            'BookId' => 'super-book-1',
            'Author' => 'Unknown',
        ],
        table: ['Books', 'BookId'],
    )
    ->put(
        [
            'BookId' => 'super-book-2',
            'Author' => 'Incognito',
        ],
        table: ['Books', 'BookId'],
    )
    ->delete(
        [
            'BookId' => 'super-book-3',
        ],
        table: ['Books', 'BookId'],
    )
    ->dispatch();

表作为对象(推荐)

使用表对象的示例

use Terseq\Builders\Table;

class Books extends Table 
{
    public function getTableName(): string
    {
        return 'Books';
    }

    public function getKeys(): Keys
    {
        return new Keys(partitionKey: 'BookId', sortKey: null);
    }
}

使用 二级索引 的示例

use Terseq\Builders\Table;

class BooksTable extends Table 
{
    /**
     * Table name
     */
    public function getTableName(): string
    {
        return 'Books';
    }

    /**
     * Partition key and sort key (optional)
     */
    public function getKeys(): Keys
    {
        return new Keys(partitionKey: 'BookId', sortKey: 'ReleaseDate');
    }

    /**
     * Secondary index map (optional) also known as GSI and LSI
     */
    public function getSecondaryIndexMap(): ?array
    {
        return [
            'AuthorIndex' => new Keys(partitionKey: 'AuthorId', sortKey: 'AuthorBornYear'),
            'GenreIndex' => new Keys(partitionKey: 'GenreId', sortKey: 'GenreName'),
            'LsiExample' => new Keys(partitionKey: 'BookId', sortKey: 'AuthorBornYear'),
        ];
    }
}

表作为数组

table(table: ['TableName', 'PartitionKey', 'SortKey']);

table(table: ['TableName', 'PartitionKey']); // Sort key by default is null

table(table: ['TableName']); // throws exception, because PartitionKey is required

table(table: [
    'table' => 'TableName',
    'pk' => 'PartitionKey',
    'sk' => 'SortKey',
]);

单表设计(推荐)

库支持 单表设计

使用单表设计的示例

$manager = new \Terseq\DatabaseManager(
    client: $client, 
    marshaler: new Marshaler(),
    singleTable: new class extends \Terseq\Builders\Table {
        public function getTableName(): string
        {
            return 'Books';
        }
        
        public function getKeys(): Keys
        {
            return new Keys(partitionKey: 'BookId');
        }
    },
);

这就完了!现在您可以构建查询而无需传递表名和键。

使用方法

// Query
$manager->getItem()->pk('super-cool-id')->disaptch();

$manager->batchWriteItem()
    ->put(
        [
            'BookId' => 'super-book-1',
            'Author' => 'Unknown',
        ],
    )
    ->put(
        [
            'BookId' => 'super-book-2',
            'Author' => 'Incognito',
        ],
    )
    ->delete(
        [
            'BookId' => 'super-book-3',
        ],
    )
    ->dispatch();

与 AWS SDK 的比较

使用 AWS SDK 的示例

$client->updateItem(
    [
        'TableName' => 'Books',
        'UpdateExpression' => 'SET #Title = :title_0, #Author = :author_0',
        'ExpressionAttributeNames' =>
            [
                '#Title' => 'Title',
                '#Author' => 'Author',
            ],
        'ExpressionAttributeValues' =>
            [
                ':title_0' =>
                    [
                        'S' => 'Super Cool Book Updated',
                    ],
                ':author_0' =>
                    [
                        'S' => 'Super Cool Author Updated',
                    ],
            ],
        'Key' =>
            [
                'BookId' =>
                    [
                        'S' => 'super-cool-id',
                    ],
            ],
    ],
);

使用 Terseq 的示例

执行相同操作

$manager->updateItem()
    ->table(['Books', 'BookId'])
    ->pk('super-cool-id')
    ->set('Title', 'Super Cool Book Updated')
    ->set('Author', 'Super Cool Author Updated')
    ->dispatch();