baopham / dynamodb
DynamoDB的Eloquent语法
Requires
- aws/aws-sdk-php: ^3.0.0
- illuminate/database: 5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0
- illuminate/support: 5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0
Requires (Dev)
- orchestra/testbench: ~3.0 || ~5.0|^8.0
- dev-master
- 6.5.0
- 6.4.0
- 6.3.0
- 6.2.0
- 6.1.3
- 6.1.2
- 6.1.1
- 6.1.0
- 6.0.0
- 5.0.1
- 5.0.0
- 4.12.0
- 4.11.2
- 4.11.1
- 4.11.0
- 4.10.0
- 4.9.0
- 4.8.2
- 4.8.1
- 4.8.0
- 4.7.0
- 4.6.1
- 4.6.0
- 4.5.0
- 4.4.0
- 4.3.2
- 4.3.1
- 4.3.0
- 4.2.3
- 4.2.2
- 4.2.1
- 4.2.0
- 4.1.1
- 4.1.0
- 4.0.0
- 3.0.1
- 3.0.0
- 2.0.3
- 2.0.2
- 2.0.1
- 2.0.0
- v1.x-dev
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7.0
- 1.6.1
- 1.6.0
- 1.5.0
- 1.4.0
- 1.3.0
- 1.2.0
- 1.1.0
- 1.0.0
- 0.10.0
- 0.9.0
- 0.8.0
- 0.7.0
- 0.6.2
- 0.6.1
- 0.6.0
- 0.5.1
- 0.5.0
- 0.4.2
- 0.4.1
- 0.4.0
- 0.3.2
- 0.3.1
- 0.3.0
- 0.2.3
- 0.2.2
- 0.2.1
- 0.2.0
- 0.1.2
- 0.1.1
- 0.1.0
- dev-role-support
- dev-transaction
- dev-test-149
- dev-feature/127-after-supports-raw-value
- dev-phpcs
- dev-code-standard
- dev-bao/exp
This package is auto-updated.
Last update: 2024-09-14 03:13:27 UTC
README
支持所有键类型 - 主哈希键和组合键。
仅适用于高级用户。如果您不熟悉Laravel、Laravel Eloquent和DynamoDB,则建议您首先熟悉这些内容。
v2版本中的破坏性变更:配置不再位于config/services.php中
安装
-
Composer安装
composer require baopham/dynamodb
-
安装服务提供者 (< Laravel 5.5)
// config/app.php 'providers' => [ ... BaoPham\DynamoDb\DynamoDbServiceProvider::class, ... ];
-
运行
php artisan vendor:publish --provider 'BaoPham\DynamoDb\DynamoDbServiceProvider'
-
在config/dynamodb.php中更新DynamoDb配置
Lumen
-
尝试这个来安装
vendor:publish
命令 -
在
bootstrap/app.php
中加载配置文件并启用Eloquent支持$app = new Laravel\Lumen\Application( realpath(__DIR__.'/../') ); // Load dynamodb config file $app->configure('dynamodb'); // Enable Facade support $app->withFacades(); // Enable Eloquent support $app->withEloquent();
用法
- 通过扩展
BaoPham\DynamoDb\DynamoDbModel
来扩展您的模型,然后您可以使用受支持的Eloquent方法。这里的想法是,您可以在不更改查询的情况下切换回Eloquent。 - 或者,如果您想将数据库表与DynamoDb表同步,请使用特质
BaoPham\DynamoDb\ModelTrait
,它将在模型保存后调用PutItem
。 - 或者,您可以使用查询构建器外观构建更复杂的查询。
- AWS SDK v3 for PHP使用guzzlehttp promises来允许异步工作流。使用此包,您可以在DynamoDb上异步运行诸如delete、update、save之类的Eloquent查询。
支持的功能
find() 和 delete()
$model->find($id, array $columns = []); $model->findMany($ids, array $columns = []); $model->delete(); $model->deleteAsync()->wait();
条件
// Using getIterator() // If 'key' is the primary key or a global/local index and it is a supported Query condition, // will use 'Query', otherwise 'Scan'. $model->where('key', 'key value')->get(); $model->where(['key' => 'key value']); // Chainable for 'AND'. $model->where('foo', 'bar') ->where('foo2', '!=', 'bar2') ->get(); // Chainable for 'OR'. $model->where('foo', 'bar') ->orWhere('foo2', '!=', 'bar2') ->get(); // Other types of conditions $model->where('count', '>', 0)->get(); $model->where('count', '>=', 0)->get(); $model->where('count', '<', 0)->get(); $model->where('count', '<=', 0)->get(); $model->whereIn('count', [0, 100])->get(); $model->whereNotIn('count', [0, 100])->get(); $model->where('count', 'between', [0, 100])->get(); $model->where('description', 'begins_with', 'foo')->get(); $model->where('description', 'contains', 'foo')->get(); $model->where('description', 'not_contains', 'foo')->get(); // Nested conditions $model->where('name', 'foo') ->where(function ($query) { $query->where('count', 10)->orWhere('count', 20); }) ->get(); // Nested attributes $model->where('nestedMap.foo', 'bar')->where('list[0]', 'baz')->get();
whereNull() 和 whereNotNull()
NULL 和 NOT_NULL仅检查属性是否存在,而不是其值是否为null
查看:http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
$model->whereNull('name'); $model->whereNotNull('name');
all() 和 first()
// Using scan operator, not too reliable since DynamoDb will only give 1MB total of data. $model->all(); // Basically a scan but with limit of 1 item. $model->first();
分页
遗憾的是,DynamoDb中跳过多少条记录的偏移量没有意义。相反,请提供上一次查询的最后结果作为下一次查询的起点。
示例
对于查询
$query = $model->where('count', 10)->limit(2); $items = $query->all(); $last = $items->last();
将此查询结果的最后一个项目作为下一个"偏移量"
$nextPage = $query->after($last)->limit(2)->all(); // or $nextPage = $query->afterKey($items->lastKey())->limit(2)->all(); // or (for query without index condition only) $nextPage = $query->afterKey($last->getKeys())->limit(2)->all();
update()
// update $model->update($attributes);
updateAsync()
// update asynchronously and wait on the promise for completion. $model->updateAsync($attributes)->wait();
save()
$model = new Model(); // Define fillable attributes in your Model class. $model->fillableAttr1 = 'foo'; $model->fillableAttr2 = 'foo'; // DynamoDb doesn't support incremented Id, so you need to use UUID for the primary key. $model->id = 'de305d54-75b4-431b-adb2-eb6b9e546014'; $model->save();
saveAsync()
异步保存单个模型并等待完成。
$model = new Model(); // Define fillable attributes in your Model class. $model->fillableAttr1 = 'foo'; $model->fillableAttr2 = 'bar'; // DynamoDb doesn't support incremented Id, so you need to use UUID for the primary key. $model->id = 'de305d54-75b4-431b-adb2-eb6b9e546014'; $model->saveAsync()->wait();
异步保存多个模型并等待所有模型同时完成。
for($i = 0; $i < 10; $i++){ $model = new Model(); // Define fillable attributes in your Model class. $model->fillableAttr1 = 'foo'; $model->fillableAttr2 = 'bar'; // DynamoDb doesn't support incremented Id, so you need to use UUID for the primary key. $model->id = uniqid(); // Returns a promise which you can wait on later. $promises[] = $model->saveAsync(); } \GuzzleHttp\Promise\all($promises)->wait();
delete()
$model->delete();
deleteAsync()
$model->deleteAsync()->wait();
chunk()
$model->chunk(10, function ($records) { foreach ($records as $record) { } });
limit() 和 take()
// Use this with caution unless your limit is small. // DynamoDB has a limit of 1MB so if your limit is very big, the results will not be expected. $model->where('name', 'foo')->take(3)->get();
firstOrFail()
$model->where('name', 'foo')->firstOrFail(); // for composite key $model->where('id', 'foo')->where('id2', 'bar')->firstOrFail();
findOrFail()
$model->findOrFail('foo'); // for composite key $model->findOrFail(['id' => 'foo', 'id2' => 'bar']);
refresh()
$model = Model::first(); $model->refresh();
查询作用域
class Foo extends DynamoDbModel { protected static function boot() { parent::boot(); static::addGlobalScope('count', function (DynamoDbQueryBuilder $builder) { $builder->where('count', '>', 6); }); } public function scopeCountUnderFour($builder) { return $builder->where('count', '<', 4); } public function scopeCountUnder($builder, $count) { return $builder->where('count', '<', $count); } } $foo = new Foo(); // Global scope will be applied $foo->all(); // Local scope $foo->withoutGlobalScopes()->countUnderFour()->get(); // Dynamic local scope $foo->withoutGlobalScopes()->countUnder(6)->get();
REMOVE — 从项目中删除属性
$model = new Model(); $model->where('id', 'foo')->removeAttribute('name', 'description', 'nested.foo', 'nestedArray[0]'); // Or Model::find('foo')->removeAttribute('name', 'description', 'nested.foo', 'nestedArray[0]');
toSql() 风格
出于调试目的,您可以将其转换为实际的DynamoDb查询
$raw = $model->where('count', '>', 10)->toDynamoDbQuery(); // $op is either "Scan" or "Query" $op = $raw->op; // The query body being sent to AWS $query = $raw->query;
其中 $raw
是 RawDynamoDbQuery 的一个实例
装饰查询
当您想增强查询时使用 decorate
。例如
设置排序键的顺序
$items = $model ->where('hash', 'hash-value') ->where('range', '>', 10) ->decorate(function (RawDynamoDbQuery $raw) { // desc order $raw->query['ScanIndexForward'] = false; }) ->get();
如果库无法检测到正确的操作,则强制使用 "Query" 而不是 "Scan"
$items = $model ->where('hash', 'hash-value') ->decorate(function (RawDynamoDbQuery $raw) { $raw->op = 'Query'; }) ->get();
索引
如果您的表有索引,请确保在您的模型类中声明它们,如下所示
/** * Indexes. * [ * '<simple_index_name>' => [ * 'hash' => '<index_key>' * ], * '<composite_index_name>' => [ * 'hash' => '<index_hash_key>', * 'range' => '<index_range_key>' * ], * ] * * @var array */ protected $dynamoDbIndexKeys = [ 'count_index' => [ 'hash' => 'count' ], ];
请注意,当键存在于多个索引中时,索引的顺序很重要。
例如,我们有一个这样的
$model->where('user_id', 123)->where('count', '>', 10)->get();
with
protected $dynamoDbIndexKeys = [ 'count_index' => [ 'hash' => 'user_id', 'range' => 'count' ], 'user_index' => [ 'hash' => 'user_id', ], ];
将使用 count_index
。
protected $dynamoDbIndexKeys = [ 'user_index' => [ 'hash' => 'user_id', ], 'count_index' => [ 'hash' => 'user_id', 'range' => 'count' ] ];
将使用 user_index
。
大多数情况下,您不需要做任何事情,但如果您需要使用特定的索引,您可以像这样指定它
$model->where('user_id', 123)->where('count', '>', 10)->withIndex('count_index')->get();
组合键
在您的模型中使用复合键
- 将
$compositeKey
设置为组成键的属性名称数组,例如
protected $primaryKey = 'customer_id'; protected $compositeKey = ['customer_id', 'agent_id'];
- 查找具有复合键的记录
$model->find(['customer_id' => 'value1', 'agent_id' => 'value2']);
查询构建器
使用 DynamoDb
门面构建原始查询
use BaoPham\DynamoDb\Facades\DynamoDb; DynamoDb::table('articles') // call set<key_name> to build the query body to be sent to AWS ->setFilterExpression('#name = :name') ->setExpressionAttributeNames(['#name' => 'author_name']) ->setExpressionAttributeValues([':name' => DynamoDb::marshalValue('Bao')]) ->prepare() // the query body will be sent upon calling this. ->scan(); // supports any DynamoDbClient methods (e.g. batchWriteItem, batchGetItem, etc.) DynamoDb::table('articles') ->setIndexName('author_name') ->setKeyConditionExpression('#name = :name') ->setProjectionExpression('id, author_name') // Can set the attribute mapping one by one instead ->setExpressionAttributeName('#name', 'author_name') ->setExpressionAttributeValue(':name', DynamoDb::marshalValue('Bao')) ->prepare() ->query(); DynamoDb::table('articles') ->setKey(DynamoDb::marshalItem(['id' => 'ae025ed8'])) ->setUpdateExpression('REMOVE #c, #t') ->setExpressionAttributeName('#c', 'comments') ->setExpressionAttributeName('#t', 'tags') ->prepare() ->updateItem(); DynamoDb::table('articles') ->setKey(DynamoDb::marshalItem(['id' => 'ae025ed8'])) ->prepare() ->deleteItem(); DynamoDb::table('articles') ->setItem(DynamoDb::marshalItem(['id' => 'ae025ed8', 'author_name' => 'New Name'])) ->prepare() ->putItem(); // Or, instead of ::table() DynamoDb::newQuery() ->setTableName('articles') // Or access the DynamoDbClient instance directly DynamoDb::client(); // pass in the connection name to get a different client instance other than the default. DynamoDb::client('test');
查询构建器方法的格式为 set<key_name>
,其中 <key_name>
是要发送的查询体中键的名称。
例如,要构建一个 UpdateTable
查询
[ 'AttributeDefinitions' => ..., 'GlobalSecondaryIndexUpdates' => ..., 'TableName' => ... ]
执行
$query = DynamoDb::table('articles') ->setAttributeDefinitions(...) ->setGlobalSecondaryIndexUpdates(...);
准备好后
$query->prepare()->updateTable();
需求
Laravel ^5.1
从v1迁移到v2
按照以下步骤操作
- 更新您的
composer.json
以使用 v2 - 运行
composer update
- 运行
php artisan vendor:publish
- 将
config/services.php
中的 DynamoDb 配置移动到新的配置文件config/dynamodb.php
作为连接之一- 将
key
、secret
、token
移动到credentials
内部 - 将
local_endpoint
重命名为endpoint
- 删除
local
字段
- 将
常见问题解答
问题:无法分配不在填充数组中的 id
属性
答案:尝试这个?
问题:如何创建迁移?
答案:请参阅此问题
问题:如何与工厂一起使用?
答案:请参阅此问题
问题:如何使用作业?获得一个 SerializesModels 错误
答案:您可以编写自己的 restoreModel 或从您的作业中删除 SerializesModels
特性。