justraviga / laravel-dynamodb-extreme
JustRaviga DynamoDb 访问包
Requires
- php: ^8.2
- aws/aws-sdk-php: ^3.269
- laravel/framework: ^10.0
Requires (Dev)
- orchestra/testbench: ^8.5
- pestphp/pest: ^2.0
- pestphp/pest-plugin-laravel: ^2.0
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2024-09-09 18:30:04 UTC
README
这是一个用于 DynamoDb 访问的查询构建器包。受其他不够优雅版本(看我在这里做了什么?)的启发,这个版本具有以下特性,就像 Laravel 一样
从 DynamoDb 获取单个 Model 实例
$model = Model::find($partitionKey, $sortKey);
或者,如果没有返回结果,则抛出 Illuminate\Database\Eloquent\ModelNotFoundException
$model = Model::findOrFail($partitionKey, $sortKey);
从 DynamoDb 获取 Model 实例的集合
注意
- 这里只支持单个 Model 类型。你必须确保你的查询只会返回相同类型的模型。
- 如果数据库中找到的属性不在模型的 $fillable 数组中,将抛出异常。
- DynamoDb 只支持 Partition 键的精确匹配,以及 Sort 键上的
<
、<=
、=
、>=
、>
、begins_with
和between
匹配。
/** @var DynamoDbResult $result */ $result = Model::where('partitionKey', $partitionKey) ->where('sortKey', 'begins_with', 'MODEL#') ->get(); /** @var \Illuminate\Support\Collection<DynamoDbModel> $models */ $models = $result->results;
你可以选择性地根据 sortKey 排序并限制结果数量
/** @var DynamoDbResult $models */ $models = Model::where('partitionKey', $partitionKey) ->sortDescending() ->limit(10) ->get();
如果你知道你将要超出 DynamoDb 的 1MB 查询大小限制,你可以使用 getAll()
方法进行多次查询,直到返回整个结果集
/** @var DynamoDbResult $models */ $models = Model::where('partitionKey', $partitionKey) ->getAll();
你也可以通过组合 limit()
和 after()
来获取特定的一组结果
$twoResults = Model::where('partitionKey', $partitionKey) ->limit(2) ->get(); $twoMoreResults = Model::where('partitionKey', $partitionKey) ->after($twoResults->lastEvaluatedKey) ->limit(2) ->get();
这是 paginate
方法中内置的快捷方式
$twoResults = Model::where('partitionKey', $partitionKey) ->limit(2) ->paginate(); $twoMoreResults = Model::where('partitionKey', $partitionKey) ->limit(2) ->paginate($twoResults->lastEvaluatedKey());
使用辅助索引获取模型集合
只要辅助索引配置正确(见下文),它就会从你正在查询的域中检测到。
/** @var \Illuminate\Support\Collection<Model> $models */ $models = Model::where('index_partition_key', $partitionKey) ->where('index_sort_key', $sortKey) ->get();
在 DynamoDb 中创建 Model 实例
立即使用 create
持久化模型
$model = Model::create([ 'partitionKey' => 'value', 'sortKey' => 'value', // other attributes... ]);
使用 make
在内存中构建模型而不进行数据库查询
$model = Model::make([ 'partitionKey' => 'value', 'sortKey' => 'sortKey', // other attributes... ]); // persist the model $model->save();
或者使用 new Model()
语法
$model = new Model([ 'partitionKey' => 'value', 'sortKey' => 'value', // other attributes ]); // persist the model $model->save();
访问模型属性
创建你的模型后,属性访问方式与 Laravel 相同,使用对象属性语法
$model = Model::find($partitionKey, $sortKey); $model->someAttribute = 'value';
你可以使用 fill
方法同时更新多个属性
$model = Model::find($partitionKey, $sortKey); $model->fill([ 'someAttribute' => 'value', // other attributes ]);
这些更改不会自动持久化回 Dynamo,你需要手动保存它们
$model = Model::find($partitionKey, $sortKey); $model->someAttribute = 'value'; $model->save();
或者
$model = Model::find($partitionKey, $sortKey); $model->fill([ 'someAttribute' => 'value', ])->save();
或者,甚至可以将 fill
和 save
结合起来
$model = Model::find($partitionKey, $sortKey); $model->update([ 'someAttribute' => 'value', ]);
设置和全局配置
环境变量
DYNAMODB_REGION
默认为localhost
,应设置为你的主 DynamoDb 实例区域(例如 eu-west-2)DYNAMODB_VERSION
默认为latest
,如果需要,应设置为你的 DynamoDb 实例版本DYNAMODB_KEY
你的 DynamoDb 访问密钥(用户名)DYNAMODB_SECRET
你的 DynamoDb 密钥(密码)DYNAMODB_ENDPOINT
默认为https://:8000
,这是你的 DynamoDb 安装地址DYNAMODB_TABLE
定义所有模型的默认表(当在特定应用程序中使用单表设计时很有用)DYNAMODB_CONSISTENT_READ
默认为true
,用于设置默认的一致性读取值(仍然可以被特定模型覆盖)DYNAMODB_LOG_QUERIES
默认为false
,用于为所有 DynamoDb 查询添加日志(发送到 Dynamo 的 json 对象将被记录)
配置选项
可以使用 Laravel 的 publish 命令导出配置文件: php artisan vendor:publish
,它看起来像这样
[ 'region' => env('DYNAMODB_REGION', 'localhost'), 'version' => env('DYNAMODB_VERSION', 'latest'), 'credentials' => [ 'key' => env('DYNAMODB_KEY', ''), 'secret' => env('DYNAMODB_SECRET', ''), ], 'endpoint' => env('DYNAMODB_ENDPOINT', 'https://:8000'), 'defaults' => [ 'consistent_read' => env('DYNAMODB_CONSISTENT_READ', true), 'table' => env('DYNAMODB_TABLE', 'default'), 'partition_key' => 'pk', 'sort_key' => 'sk', 'global_secondary_indexes' => [ 'gsi1' => [ 'pk' => 'gsi1_pk', 'sk' => 'gsi1_sk', ] ], 'log_queries' => env('DYNAMODB_LOG_QUERIES', false), ], ]
除了基于环境的配置之外,你还可以指定分区键、排序键和全局辅助索引的默认值。这些默认值是基于 DynamoDb 的一般使用模式而设定的。
模型配置
创建模型很容易。至少,你需要定义表名、partitionKey 和 sortKey,以及一个“fillable”属性数组(注意,分区和排序键必须是可填充的!)
class Model extends \DynamoDb\Models\DynamoDbModel { // optional, see environment variable for table name protected string $table = 'models'; // optional, see environment variable for partition/sort keys protected string $partitionKey = 'pk'; protected string $sortKey = 'sk'; // required! must include at least partition/sort keys public array $fillable = [ 'pk', 'sk', // other attributes... ]; }
为了编写更详细的代码,您可以通过覆盖受保护的属性 fieldMappings
来创建从内部/数据库字段到友好属性的映射。映射在从数据库获取数据以及将数据保存到数据库时应用。其余时间,您始终使用映射的属性名称。
class Model extends \DynamoDb\Models\DynamoDbModel { // optional protected array $fieldMappings = [ 'pk' => 'my_uuid', 'sk' => 'created_date', ]; }
默认情况下,所有模型的分区键都是以模型类名后跟一个 #
然后是一个 UUID-7(时间顺序 UUID)来构建的。排序键默认为模型名称。例如
class Model extends \DynamoDb\Models\DynamoDbModel { } $model = new Model(); // partition key = 'MODEL#{uuid-7} // sort key = 'MODEL'
您也可以通过覆盖这些方法在创建新模型时更改这些默认值
class Model extends \DynamoDb\Models\DynamoDbModel { public function defaultPartitionKey(): string { return 'MODEL#' . random_int(0,1000); } public function defaultSortKey(): string { return 'CREATED_AT#' . now()->toISOString(); } public function defaultValues(): array { return [ 'attribute' => 'default value', ]; } }
相关模型
您可以通过一些额外的设置来配置具有相同分区键的相关模型
class ParentModel extends \DynamoDb\Models\DynamoDbModel { public function childModels(): \DynamoDb\DynamoDb\Relation { return $this->addRelation(ChildModel::class); } }
默认情况下,这使用父模型的分区键,并通过“begins_with”查询与子模型类名后跟一个哈希(#)进行匹配,例如 begins_with(sk, 'CHILDMODEL#')
。匹配本身可以通过在子模型上覆盖 relationSearchParams
方法进行配置
class ChildModel extends \DynamoDb\Models\DynamoDbModel { public static function relationSearchParams(): array { return [ 'sk', 'begins_with', 'CLASSNAME#' ]; } }
您可以使用与关系方法同名的属性来作为集合访问相关模型
class Model extends \DynamoDb\Models\DynamoDbModel { public function children(): \DynamoDb\DynamoDb\Relation { return $this->addRelation(Child::class); } } $model = Model::find(...); $model->children->map(fn ($child) => $child->doSomething());
“内联”关系
除了在 DynamoDb 表的不同行中保存相关模型外,您还可以使用记录上的 JSON 属性作为关系。我们称这种关系为“内联关系”,并且它们可以像其他关系一样访问
class Model extends \DynamoDb\Models\DynamoDbModel { public function inline(): InlineRelation { return $this->addInlineRelation(Inline::class, 'inline'); } } $model = Model::find(...); $model->inline->map(fn ($child) => $child->doSomething());
如果您想在表上使用辅助索引,只需在 $indexes
数组中定义分区和排序键名称。请确保将它们添加到 $fillable
数组中。
class Model extends \DynamoDb\Models\DynamoDbModel { // optional, see config values protected array $indexes = [ 'gsi1' => [ 'pk' => 'gsi1_pk', 'sk' => 'gsi1_sk', ], ]; // required if you want to use a secondary index public array $fillable = [ 'gsi1_pk', 'gsi1_sk', // other attributes... ]; }
您也可以在 $fieldMappings
数组中定义从辅助索引到友好模型属性的映射。
class Model extends \JustRaviga\LaravelDynamodbExtreme\Models\DynamoDbModel { // optional protected array $fieldMappings = [ 'gsi1_pk' => 'user_uuid', 'gsi1_sk' => 'created_date', ]; }
最低要求
- PHP 8.2
- Laravel 10.0
愿望清单
我们可能想要包括但最终没有时间充分考虑的事情
将 DynamoDb 响应包装在缓存层中
可选地将从 DynamoDb 获取的模型存储在内存中,以便在请求期间重复使用相同的分区/排序键而无需查询 Dynamo。
属性转换
类似于 Laravel 模型的 $casts 数组,在从 DynamoDb 获取和保存时,应将这些数据类型转换为属性。
扩展 Collection 类以包含基于 DynamoDb 模型的过滤方法
Collection 类上的新方法,用于基于 DynamoDb 的 Last Evaluated Key 进行分页。
更好的文档 🙈
文档总是可以改进的。
并发请求
找出如何进行许多可以 await 的并发请求,并且只有当所有请求都返回其数据时才继续执行。
代码生成表
基本上是 Laravel 的 DynamoDb 表迁移系统
级联删除
在删除父模型后删除相关模型