musonza/dynamo-breeze

一个用于通过单表方法轻松与DynamoDB交互的Laravel包。

v0.0.3 2023-10-24 22:48 UTC

This package is auto-updated.

Last update: 2024-09-27 02:16:48 UTC


README

DynamoBreeze 是一个Laravel包,旨在简化与Amazon DynamoDB的交互。虽然它符合单表设计原则,但它足够灵活,可以支持多表使用,无论您的数据库架构如何,都能提供无缝的体验。重要的是,它允许使用多个AWS凭证,这是需要访问不同AWS账户中的表或使用特定IAM密钥访问某些表的应用程序的关键功能。通过流畅的、易于表达的门面,DynamoBreeze使与DynamoDB的交互变得前所未有的简单。

关键特性

  • 支持单表或多表:无论您是遵循单表设计还是使用多表,DynamoBreeze都能适应您的需求,允许您以高效的方式与数据交互,而无需复杂性。

  • 支持多个AWS凭证:DynamoBreeze的架构支持为不同的表使用不同的AWS凭证,非常适合与多个AWS账户交互或将特定的密钥和秘密应用于单个表。这种功能确保了在多样化的环境中管理数据时的灵活性和安全性。

  • 易于表达的语法:利用流畅的语法来构建您的DynamoDB查询,使它们更易于阅读和维护。

  • 简化配置:在中心配置中定义您的表结构和访问模式,使管理查询数据变得简单。

  • 可定制:开箱即用,但考虑到定制,因此您可以根据应用程序的需求进行调整。

目录

安装

通过Composer

composer require musonza/dynamo-breeze

配置

安装包后,通过运行以下命令发布配置文件

php artisan vendor:publish --provider="Musonza\DynamoBreeze\DynamoBreezeServiceProvider"

示例用法

使用DynamoBreeze门面,您可以以更易于表达和直接的方式与DynamoDB交互。以下是使用示例

以下是一个使用DynamoBreeze包与DynamoDB交互的基本示例。DynamoBreeze旨在适应单表设计原则,这意味着您可以创建一个通用的表来托管多个实体,并有效地利用各种访问模式。

在您的 dynamo-breeze.php 配置文件中

return [
    // 'tables' holds the configuration for all the DynamoDB tables that this package will interact with.
    'tables' => [
        // Each table has its own configuration nested under a unique logical identifier used in your application code to reference the table configuration.
        'social_media' => [
            /*
            * 'table_name' is the name of the DynamoDB table as defined in AWS.
            */
            'table_name' => 'SocialMediaTable',

            /*
            * 'partition_key' specifies the primary key attribute name of the table.
            */
            'partition_key' => 'PK',

            /*
            * 'sort_key' specifies the sort key attribute name of the table.
            * If a table doesn't have a sort key, you can omit this field.
            */
            'sort_key' => 'SK',

            /*
            * 'attributes' define the attributes and their types that the model will interact with.
            * It's used for actions like creating tables or validating input.
            * Common types: 'S' => String, 'N' => Number, 'B' => Binary.
            */
            'attributes' => [
                'PK' => 'S',
                'SK' => 'S',
                // ...
            ],

            /*
            * 'access_patterns' define various access patterns to use with the table.
            * Each access pattern has a unique name and associated settings.
            */
            'access_patterns' => [
                'FetchUserPosts' => [
                    'gsi_name' => null,
                    'key_condition_expression' => 'PK = :pk_val AND begins_with(SK, :sk_prefix_val)',
                    'expression_attribute_values' => [
                        ':pk_val' => ['S' => 'USER#<user_id>'],
                        ':sk_prefix_val' => ['S' => 'POST#'],
                    ],
                ],
                'FetchPostComments' => [
                    'gsi_name' => null,
                    'key_condition_expression' => 'PK = :pk_val AND begins_with(SK, :sk_prefix_val)',
                    'expression_attribute_values' => [
                        ':pk_val' => ['S' => 'POST#<post_id>'],
                        ':sk_prefix_val' => ['S' => 'COMMENT#'],
                    ],
                ],
                // ...
            ],
            'credentials' => 'other_account',
            // ... additional settings for the table
        ],
        
        /*
        * Additional tables, such as 'products', can have similar configurations.
        * Adapt each table configuration to match its structure and access patterns in DynamoDB.
        */
        'products' => [
            // ... configuration for the 'products' table
        ],
        // ... configurations for other tables
    ],

    /*
    * 'sdk' holds the configuration for the AWS SDK.
    */
    'credentials' => [
        'default' => [ // Default credential set
            'region' => env('DYNAMODB_REGION', 'us-west-2'),
            'version' => env('DYNAMODB_VERSION', 'latest'),
            'endpoint' => env('DYNAMODB_ENDPOINT'),
            'credentials' => [
                'key' => env('AWS_ACCESS_KEY_ID'),
                'secret' => env('AWS_SECRET_ACCESS_KEY'),
            ],
        ],

        'other_account' => [ // Credentials for another AWS account
            'region' => env('DYNAMODB_OTHER_REGION', 'us-east-1'),
            'version' => env('DYNAMODB_VERSION', 'latest'),
            'endpoint' => env('DYNAMODB_ENDPOINT'),
            'credentials' => [
                'key' => env('AWS_OTHER_ACCESS_KEY_ID'),
                'secret' => env('AWS_OTHER_SECRET_ACCESS_KEY'),
            ],
        ],

        // 'another_set' => [
        //     // ...
        // ],
    ],
];

获取用户帖子

use Musonza\DynamoBreeze\Facades\DynamoBreeze;

$result = DynamoBreeze::withTableIdentifier('social_media')
    ->accessPattern('FetchUserPosts', [
        'user_id' => $userId,
    ])
    ->projectionExpression('Content, CategoryId') // specify ProjectionExpression
    ->get();

获取帖子评论

$comments = DynamoBreeze::withTableIdentifier('social_media')
    ->accessPattern('FetchPostComments', [
        'post_id' => $postId,
    ])
    ->get();

使用DynamoBreezeResult处理响应

通过DynamoBreeze门面执行的所有操作都将返回一个 DynamoBreezeResult 实例。该对象提供了一个方便的方式与DynamoDB返回的数据交互,提供了几种方法来检索AWS结果中的特定部分或整个原始结果。

可用方法

  • getItems():返回结果中的项目数组。如果没有找到项目,则返回null。

  • getCount():检索返回的项目数。如果没有提供计数,则返回null。

  • getRawResult():提供对原始 Aws\Result 对象的访问,允许您检索从AWS SDK的DynamoDB客户端返回的任何数据或元数据。

示例

use Musonza\DynamoBreeze\Facades\DynamoBreeze;

// Perform an operation
$result = DynamoBreeze::withTableIdentifier('social_media')
    ->accessPattern('FetchUserPosts', [
        'user_id' => $userId,
    ])
    ->limit(10)
    ->exclusiveStartKey($startKey)
    ->projectionExpression('Content, CategoryId')
    ->get();

// Get the items returned from DynamoDB
$items = $result->getItems();

// Get the count of items
$count = $result->getCount();

// Access the raw AWS SDK result object
$rawResult = $result->getRawResult();

扩展查询参数映射

DynamoBreeze提供一组核心映射,将特定的配置键转换为相应的DynamoDB查询参数。这些映射在内部用于根据您应用程序的配置构建查询。

虽然默认映射覆盖了广泛的常见用例,但仍可能有需要扩展或覆盖这些映射的场景。对于此类情况,DynamoBreeze通过additional_query_mappings配置提供了一个灵活的解决方案。

添加自定义映射

如果您需要添加不在默认集合中的新映射,您可以在应用程序的dynamo-breeze配置文件中的additional_query_mappings键下定义它们。

以下是如何设置additional_query_mappings:的示例

// In your config/dynamo-breeze.php configuration file

return [
    'tables' => [],
    // ... other configuration values ...

    'additional_query_mappings' => [
        'your_config_key' => 'DynamoQueryParam',
        // other custom mappings...
    ],
];

在这个例子中,your_config_key是您在应用程序配置中使用的键,而DynamoQueryParam是DynamoDB在查询中期望的相应参数。

用例

添加自定义映射的实用用例之一可能是当您使用DynamoBreeze默认映射尚未涵盖的DynamoDB的新功能时。通过添加必要的映射,您确保您的应用程序可以充分利用所有DynamoDB功能,同时保持使用DynamoBreeze的便利性。

分页

DynamoDB不会在单个响应中返回所有项目;相反,它对结果进行分页。DynamoBreeze简化了分页过程,让您可以轻松地浏览记录。这对于处理大型数据集尤其有用。

示例分页

假设您想检索特定用户的全部帖子,但由于数据量较大,DynamoDB对结果进行了分页。以下是使用DynamoBreeze处理分页的方法

$startKey = null;
$retrievedItemsCount = 0;
$pageSize = 10; // Define your page size
$userId = 1; // The user whose posts we are fetching

do {
    /** @var DynamoBreezeResult $result */
    $result = DynamoBreeze::withTableIdentifier(self::TABLE_IDENTIFIER)
        ->accessPattern('FetchUserPosts', ['user_id' => $userId]) // Specify access pattern and relevant data
        ->limit($pageSize) // Limit the number of items fetched per request
        ->exclusiveStartKey($startKey) // Identify the starting point for the next set of results
        ->get(); // Execute the query

    $items = $result->getItems(); // Retrieve the items from the current page
    $retrievedItemsCount += $result->getCount(); // Increment the count

    // Check if there are more pages of results
    $startKey = $result->getLastEvaluatedKey();
} while ($startKey !== null);

// At this point, $retrievedItemsCount contains the total count of items retrieved
// And $items contains the items from the last fetched page

使用batchGet进行批量检索

当与DynamoDB一起工作时,可能会有需要通过主键检索多个项目的情况。DynamoBreeze提供的batchGet方法允许在单个操作中检索一个或多个表中的多个项目,这比发出多个GetItem请求更有效。

在以下示例中,我们正在从存储在两个不同表中的多个用户处检索帖子。我们使用batchGet从TableTwo和TableTwo检索项目,使用它们的键。

// Define the keys for the items we want to retrieve.
$tableOneKeysToGet = [
    ['PK' => 'USER#1', 'SK' => 'POST#123'],
    ['PK' => 'USER#1', 'SK' => 'POST#124'],
    ['PK' => 'USER#2', 'SK' => 'POST#123'],
    ['PK' => 'USER#3', 'SK' => 'POST#1'],
];

$tableTwoKeysToGet = [
    ['PostId' => '1', 'Timestamp' => 11111],
];

$result = DynamoBreeze::batchGet([
        'table_one_identifier' => [
            'keys' => $tableOneKeysToGet,
        ],
        'table_two_table_identifier' => [
            'keys' => $tableTwoKeysToGet,
        ],
    ]);

投影表达式

在数据库操作领域,尤其是在处理大量数据集时,只检索必要的数据对于性能优化至关重要。在DynamoDB和DynamoBreeze的上下文中,这种选择性检索属性是通过所谓的“投影表达式”来处理的。

$result = DynamoBreeze::withTableIdentifier('social_media')
    ->accessPattern('FetchUserPosts', [
        'user_id' => $userId,
    ])
    ->projectionExpression('Content, CategoryId')
    ->get();

返回消耗的容量

检索特定操作消耗的容量单位的能力对于跟踪使用情况和成本至关重要。returnConsumedCapacity方法用于指定是否返回操作消耗的容量单位。以下是它的使用方法

DynamoBreeze::withTableIdentifier('social_media')
    ->returnConsumedCapacity('TOTAL')
    ->accessPattern('FetchUserPosts', ['user_id' => $userId])
    ->get();

Dynamo Breeze模式详情

在开发Laravel的过程中,您可能会发现经常需要与DynamoDB表的配置细节交互。dynamo-breeze:patterns Artisan命令提供了一个清晰的概述。此命令获取并整洁地显示DynamoDB表的访问模式,有助于快速验证和参考。以下是一个展示信息结构的示例输出

~/Development/laravel ❯ php artisan dynamo-breeze:patterns                                                                                                                          

Table: example_table
+--------------------------------+------------------------------------------------------------------+
| Pattern                        | Details                                                          |
+--------------------------------+------------------------------------------------------------------+
| ExampleAccessPattern           | {                                                                |
|                                |     "index_name": "GSI_UserTimestamp",                           |
|                                |     "key_condition_expression": "UserId = :userIdVal",           |
|                                |     "filter_expression": null,                                   |
|                                |     "expression_attribute_values": null                          |
|                                | }                                                                |
| ExampleAccessPatternWithFilter | {                                                                |
|                                |     "index_name": "GSI_UserTimestamp",                           |
|                                |     "key_condition_expression": "UserId = :userIdVal",           |
|                                |     "filter_expression": "Age > :minAge",                        |
|                                |     "expression_attribute_values": {                             |
|                                |         ":pk_val": {                                             |
|                                |             "S": "USER#<user_id>"                                |
|                                |         },                                                       |
|                                |         ":minAge": {                                             |
|                                |             "N": "<age>"                                         |
|                                |         }                                                        |
|                                |     }                                                            |
|                                | }                                                                |
| FetchUserPosts                 | {                                                                |
|                                |     "key_condition_expression": "PK = :pk_val AND SK = :sk_val", |
|                                |     "expression_attribute_values": {                             |
|                                |         ":pk_val": {                                             |
|                                |             "S": "USER#<user_id>"                                |
|                                |         },                                                       |
|                                |         ":sk_val": {                                             |
|                                |             "N": "<timestamp>"                                   |
|                                |         }                                                        |
|                                |     }                                                            |
|                                | }                                                                |
+--------------------------------+------------------------------------------------------------------+

测试

composer test

贡献

欢迎贡献,并将获得全额认可。请参阅获取详细信息。

许可证

DynamoBreeze是开源软件,许可协议为MIT许可

联系

对于一般问题、头脑风暴和开放式讨论,请使用我们的GitHub Discussions。这是一个开始社交化想法、寻求其他社区成员的帮助或讨论与项目相关的更广泛主题的好地方。请记住,新的视角可能非常有价值,您的见解可能会激发下一个重大功能或改进。