{"id":37235867,"url":"https://github.com/kitar/laravel-dynamodb","last_synced_at":"2026-01-16T04:51:23.130Z","repository":{"id":43099127,"uuid":"245631436","full_name":"kitar/laravel-dynamodb","owner":"kitar","description":"A DynamoDB based Eloquent model and Query builder for Laravel.","archived":false,"fork":false,"pushed_at":"2025-06-09T02:45:28.000Z","size":139,"stargazers_count":192,"open_issues_count":7,"forks_count":29,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-12-01T09:09:09.936Z","etag":null,"topics":["aws","dynamodb","eloquent","laravel","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kitar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-07T12:46:33.000Z","updated_at":"2025-11-12T20:39:51.000Z","dependencies_parsed_at":"2024-06-19T16:22:07.176Z","dependency_job_id":"5d5e1f26-3e81-4c3b-bc5a-c99c04740849","html_url":"https://github.com/kitar/laravel-dynamodb","commit_stats":{"total_commits":82,"total_committers":10,"mean_commits":8.2,"dds":"0.19512195121951215","last_synced_commit":"0e769043d2ddb55fc695120b79bd4e0e1df6618b"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/kitar/laravel-dynamodb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitar%2Flaravel-dynamodb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitar%2Flaravel-dynamodb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitar%2Flaravel-dynamodb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitar%2Flaravel-dynamodb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kitar","download_url":"https://codeload.github.com/kitar/laravel-dynamodb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitar%2Flaravel-dynamodb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28420813,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","dynamodb","eloquent","laravel","php"],"created_at":"2026-01-15T04:04:37.596Z","updated_at":"2026-01-15T04:04:38.139Z","avatar_url":"https://github.com/kitar.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel DynamoDB\n\n[![test](https://github.com/kitar/laravel-dynamodb/workflows/test/badge.svg)](https://github.com/kitar/laravel-dynamodb/actions)\n[![codecov](https://codecov.io/gh/kitar/laravel-dynamodb/branch/master/graph/badge.svg)](https://codecov.io/gh/kitar/laravel-dynamodb/branch/master)\n\nA DynamoDB based Eloquent model and Query builder for Laravel.\n\nYou can find an example implementation in [kitar/simplechat](https://github.com/kitar/simplechat).\n\n- [Motivation](#motivation)\n- [Installation](#installation)\n  * [Laravel](#laravel)\n  * [Non-Laravel projects](#non-laravel-projects)\n- [Sample data](#sample-data)\n- [Model](#model)\n  * [Extending the base model](#extending-the-base-model)\n  * [Basic Usage](#basic-usage)\n    + [Retrieving all models](#retrieving-all-models)\n    + [Retrieving a model](#retrieving-a-model)\n    + [create()](#create)\n    + [save()](#save)\n    + [update()](#update)\n    + [delete()](#delete)\n    + [increment() / decrement()](#increment--decrement)\n  * [Advanced Queries](#advanced-queries)\n- [Authentication with model](#authentication-with-model)\n  * [Register custom user provider](#register-custom-user-provider)\n  * [Change auth config](#change-auth-config)\n- [Query Builder](#query-builder)\n  * [Basic Usage](#basic-usage-1)\n    + [getItem()](#getitem)\n    + [putItem()](#putitem)\n    + [updateItem()](#updateitem)\n    + [deleteItem()](#deleteitem)\n  * [Projection Expressions](#projection-expressions)\n    + [select()](#select)\n  * [Condition Expressions](#condition-expressions)\n    + [condition()](#condition)\n    + [conditionIn()](#conditionin)\n    + [conditionBetween()](#conditionbetween)\n  * [Working with Queries](#working-with-queries)\n    + [query() and keyCondition()](#query-and-keycondition)\n    + [keyConditionBetween()](#keyconditionbetween)\n    + [Sort order](#sort-order)\n  * [Working with Scans](#working-with-scans)\n    + [scan()](#scan)\n  * [Filtering the Results](#filtering-the-results)\n    + [filter()](#filter)\n    + [filterIn()](#filterin)\n    + [filterBetween()](#filterbetween)\n  * [Paginating the Results](#paginating-the-results)\n    + [exclusiveStartKey()](#exclusivestartkey)\n  * [Using Global Secondary Indexes](#using-global-secondary-indexes)\n    + [index()](#index)\n  * [Atomic Counter](#atomic-counter)\n  * [Batch Operations](#batch-operations)\n    + [batchGetItem()](#batchgetitem)\n    + [batchPutItem()](#batchputitem)\n    + [batchDeleteItem()](#batchdeleteitem)\n    + [batchWriteItem()](#batchwriteitem)\n  * [DynamoDB-specific operators for condition() and filter()](#dynamodb-specific-operators-for-condition-and-filter)\n    + [Comparators](#comparators)\n    + [functions](#functions)\n- [Debugging](#debugging)\n- [Testing](#testing)\n\n## Motivation\n\n- I want to use DynamoDB with Laravel. (e.g., authenticate with custom user provider)\n- I want to use a simple API which doesn't need to worry about cumbersome things like manually handling Expression Attributes.\n- I want to extend Laravel's code as much as I can to:\n    - Rely on Laravel's robust codes.\n    - keep the additional implementation simple and maintainable.\n- I don't want to make it fully compatible with Eloquent because DynamoDB is different from relational databases.\n- I'm longing for [jessengers/laravel-mongodb](https://github.com/jenssegers/laravel-mongodb). What if we have that for DynamoDB?\n\n## Installation\n\nInstall the package via Composer:\n\n```\n$ composer require kitar/laravel-dynamodb\n```\n\n### Laravel (6.x, 7.x, 8.x, 9.x, 10.x, 11.x, 12.x)\n\nAdd dynamodb configs to `config/database.php`:\n\n```php\n'connections' =\u003e [\n\n    'dynamodb' =\u003e [\n        'driver' =\u003e 'dynamodb',\n        'key' =\u003e env('AWS_ACCESS_KEY_ID'),\n        'secret' =\u003e env('AWS_SECRET_ACCESS_KEY'),\n        'region' =\u003e env('AWS_DEFAULT_REGION', 'us-east-1'),\n        'token' =\u003e env('AWS_SESSION_TOKEN', null),\n        'endpoint' =\u003e env('DYNAMODB_ENDPOINT', null),\n        'prefix' =\u003e '', // table prefix\n    ],\n\n    ...\n\n],\n```\n\nUpdate the `DB_CONNECTION` variable in your `.env` file:\n\n```\nDB_CONNECTION=dynamodb\n```\n\n\u003e **Note for Laravel 11+**: Laravel 11 and later versions default to `database` driver for session, cache, and queue, which are not compatible with this DynamoDB package. You'll need to configure these services to use alternative drivers. For instance:\n\u003e\n\u003e ```\n\u003e SESSION_DRIVER=file\n\u003e CACHE_STORE=file\n\u003e QUEUE_CONNECTION=sync\n\u003e ```\n\n### Non-Laravel projects\n\nFor usage outside Laravel, you can create the connection manually and start querying with [Query Builder](#query-builder).\n\n```php\n$connection = new Kitar\\Dynamodb\\Connection([\n    'key' =\u003e env('AWS_ACCESS_KEY_ID'),\n    'secret' =\u003e env('AWS_SECRET_ACCESS_KEY'),\n    'region' =\u003e env('AWS_DEFAULT_REGION', 'us-east-1'),\n    'token' =\u003e env('AWS_SESSION_TOKEN', null),\n    'endpoint' =\u003e env('DYNAMODB_ENDPOINT', null),\n    'prefix' =\u003e '', // table prefix\n]);\n\n$connection-\u003etable('your-table')-\u003e...\n```\n\n## Sample data\n\nMany of the example codes in this document are querying to [DynamoDB's official sample data](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AppendixSampleTables.html). If you want to try these codes with actual DynamoDB tables, it's handy to load them to your tables before.\n\n## Model\n\nDynamoDB model extends Eloquent model so that we can use familiar features such as mutators, serialization, etc.\n\nThe main difference between Eloquent model and DynamoDB model is:\n\n- Eloquent model\n    - Can handle relations.\n    - Forward calls to model (Eloquent) query builder. (e.g., `create`, `createOrFirst` `where` `with`)\n- DynamoDB model\n    - Cannot handle relations.\n    - Forward calls to database (DynamoDB) query builder. (e.g., `getItem`, `putItem`, `scan`, `filter`)\n\n### Extending the base model\n\nMost of the attributes are the same as the original Eloquent model, but there are few DynamoDB-specific attributes.\n\n| Name           | Required | Description                     |\n|----------------|----------|---------------------------------|\n| table          | yes      | Name of the Table.              |\n| primaryKey     | yes      | Name of the Partition Key.      |\n| sortKey        |          | Name of the Sort Key.           |\n| sortKeyDefault |          | Default value for the Sort Key. |\n\nFor example, if our table has only partition key, the model will look like this:\n\n```php\nuse Kitar\\Dynamodb\\Model\\Model;\n\nclass ProductCatalog extends Model\n{\n    protected $table = 'ProductCatalog';\n    protected $primaryKey = 'Id';\n    protected $fillable = ['Id', 'Price', 'Title'];\n}\n```\n\nIf our table also has sort key:\n\n```php\nuse Kitar\\Dynamodb\\Model\\Model;\n\nclass Thread extends Model\n{\n    protected $table = 'Thread';\n    protected $primaryKey = 'ForumName';\n    protected $sortKey = 'Subject';\n    protected $fillable = ['ForumName', 'Subject'];\n}\n```\n\nIf we set `sortKeyDefault`, it will be used when we instantiate or call `find` without sort key.\n\n```php\nuse Kitar\\Dynamodb\\Model\\Model;\nuse Illuminate\\Auth\\Authenticatable;\nuse Illuminate\\Contracts\\Auth\\Authenticatable as AuthenticatableContract;\n\nclass User extends Model implements AuthenticatableContract\n{\n    use Authenticatable;\n\n    protected $table = 'User';\n    protected $primaryKey = 'email';\n    protected $sortKey = 'type';\n    protected $sortKeyDefault = 'profile';\n    protected $fillable = [\n        'name', 'email', 'password', 'type',\n    ];\n}\n```\n\n\u003e Note that this model is implementing `Illuminate\\Contracts\\Auth\\Authenticatable` and using `Illuminate\\Auth\\Authenticatable`. This is **optional**, but if we use them, we can use this model with authentication as well. For authentication, please refer to [Authentication section](#authentication-with-model)) for more details.\n\n### Basic Usage\n\n#### Retrieving all models\n\n```php\n$products = ProductCatalog::scan();\n```\n\nor alternatively,\n\n```php\n$products = ProductCatalog::all();\n```\n\nYou also can override the `scan()` method to fit your needs, such as filtering models for single table design. For example:\n\n```php\npublic static function scan($exclusiveStartKey = null, $sort = 'asc', $limit = 50)\n{\n    return static::index('GSI1')\n        -\u003ekeyCondition('GSI1PK', '=', 'PRODUCT#')\n        -\u003ekeyCondition('GSI1SK', 'begins_with', 'PRODUCT#')\n        -\u003eexclusiveStartKey($exclusiveStartKey)\n        -\u003escanIndexForward($sort == 'desc' ? false : true)\n        -\u003elimit($limit)\n        -\u003equery();\n}\n```\n\n\u003e DynamoDB can only handle result set up to 1MB per call, so we have to paginate if there are more results. see [Paginating the Results](#paginating-the-results) for more details.\n\n#### Retrieving a model\n\nIf the model has only partition key:\n\n```php\nProductCatalog::find(101);\n```\n\nIf the model also has sort key:\n\n```php\nThread::find([\n    'ForumName' =\u003e 'Amazon DynamoDB', // Partition key\n    'Subject' =\u003e 'DynamoDB Thread 1' // Sort key\n]);\n```\n\nIf the model has sort key and `sortKeyDefault` is defined:\n\n```php\nUser::find('foo@bar.com'); // Partition key. sortKeyDefault will be used for Sort key.\n```\n\nYou also can modify the behavior of the `find()` method to fit your needs. For example:\n\n```php\npublic static function find($userId)\n{\n    return parent::find([\n        'PK' =\u003e str_starts_with($userId, 'USER#') ? $userId : 'USER#'.$userId,\n        'SK' =\u003e 'USER#',\n    ]);\n}\n```\n\n#### create()\n\n```php\n$user = User::create([\n    'email' =\u003e 'foo@bar.com',\n    'type' =\u003e 'profile' // Sort key. If we don't specify this, sortKeyDefault will be used.\n]);\n```\n\n#### save()\n\n```php\n$user = new User([\n    'email' =\u003e 'foo@bar.com',\n    'type' =\u003e 'profile'\n]);\n\n$user-\u003esave();\n```\n\n```php\n$user-\u003ename = 'foo';\n$user-\u003esave();\n```\n\n#### update()\n\n```php\n$user-\u003eupdate([\n    'name' =\u003e 'foobar'\n]);\n```\n\n#### delete()\n\n```php\n$user-\u003edelete();\n```\n\n#### increment() / decrement()\n\nWhen we call `increment()` and `decrement()`, the [Atomic Counter](#atomic-counter) will be used under the hood.\n\n```php\n$user-\u003eincrement('views', 1);\n$user-\u003edecrement('views', 1);\n```\n\nWe can also pass additional attributes to update.\n\n```php\n$user-\u003eincrement('views', 1, [\n    'last_viewed_at' =\u003e '...',\n]);\n```\n\n### Advanced Queries\nWe can use Query Builder functions through model such as `query` `scan` `filter` `condition` `keyCondition` etc.\n\nFor example:\n\n```php\nThread::keyCondition('ForumName', '=', 'Amazon DynamoDB')\n    -\u003ekeyCondition('Subject', 'begins_with', 'DynamoDB')\n    -\u003efilter('Views', '=', 0)\n    -\u003equery();\n```\n\nPlease refer to [Query Builder](#query-builder) for the details.\n\n## Authentication with model\n\nWe can create a Custom User Provider to authenticate with DynamoDB. For the detail, please refer to [Laravel's official document](https://laravel.com/docs/authentication#adding-custom-user-providers).\n\nTo use authentication with the model, the model should implement `Illuminate\\Contracts\\Auth\\Authenticatable` contract. In this section, we'll use the example `User` model above.\n\n### Register custom user provider\n\nAfter we prepare authenticatable model, we need to make the custom user provider. We can make it own (it's simple), but we'll use `Kitar\\Dynamodb\\Model\\AuthUserProvider` in this section.\n\nTo register custom user provider, add codes below in `App/Providers/AuthServiceProvider.php`.\n\n```php\nuse Kitar\\Dynamodb\\Model\\AuthUserProvider;\n...\npublic function boot()\n{\n    $this-\u003eregisterPolicies();\n\n    Auth::provider('dynamodb', function ($app, array $config) {\n        return new AuthUserProvider(\n            $app['hash'],\n            $config['model'],\n            $config['api_token_name'] ?? null,\n            $config['api_token_index'] ?? null\n        );\n    });\n}\n```\n\n### Change auth config\n\nThen specify driver and model name for authentication in `config/auth.php`.\n\n```php\n'providers' =\u003e [\n    // Eloquent\n    // 'users' =\u003e [\n    //     'driver' =\u003e 'eloquent',\n    //     'model' =\u003e App\\User::class,\n    // ],\n\n    // DynamoDB\n    'users' =\u003e [\n        'driver' =\u003e 'dynamodb',\n        'model' =\u003e App\\User::class,\n        'api_token_name' =\u003e 'api_token',\n        'api_token_index' =\u003e 'api_token-index'\n    ],\n],\n```\n\n`api_token_name` and `api_token_index` are optional, but we need them if we use api token authentication.\n\n### Registration Controller\n\nYou might need to modify the registration controller. For example, if we use Laravel Starter Kits, the modification looks like below.\n\n```php\nclass RegisteredUserController extends Controller\n{\n    ...\n\n    public function store(Request $request)\n    {\n        $request-\u003evalidate([\n            'name' =\u003e 'required|string|max:255',\n            'email' =\u003e ['required', 'string', 'lowercase', 'email', 'max:255', function ($attribute, $value, $fail) {\n                if (User::find($value)) {\n                    $fail('The '.$attribute.' has already been taken.');\n                }\n            }],\n            'password' =\u003e ['required', 'confirmed', Rules\\Password::defaults()],\n        ]);\n\n        $user = User::create([\n            'name' =\u003e $request-\u003ename,\n            'email' =\u003e $request-\u003eemail,\n            'password' =\u003e Hash::make($request-\u003epassword),\n        ]);\n\n        event(new Registered($user));\n\n        Auth::login($user);\n\n        return to_route('dashboard');\n    }\n}\n```\n\nThe change is in the email validation rules. Instead of using the `unique` rule, we pass a closure to perform the duplicate check directly.\n\n## Query Builder\n\nWe can use Query Builder without model.\n\n```php\n$result = DB::table('Thread')-\u003escan();\n```\n\nOr even outside Laravel.\n\n```php\n$connection = new Kitar\\Dynamodb\\Connection([\n    'key' =\u003e env('AWS_ACCESS_KEY_ID'),\n    'secret' =\u003e env('AWS_SECRET_ACCESS_KEY'),\n    'region' =\u003e env('AWS_DEFAULT_REGION', 'us-east-1'),\n    'token' =\u003e env('AWS_SESSION_TOKEN', null),\n    'endpoint' =\u003e env('DYNAMODB_ENDPOINT', null),\n    'prefix' =\u003e '', // table prefix\n]);\n\n$result = $connection-\u003etable('Thread')-\u003escan();\n```\n\nIf we query through the model, we don't need to specify the table name, and the response will be the model instance(s).\n\n```php\n$threads = Thread::scan();\n```\n\n### Basic Usage\n\n#### getItem()\n\n```php\n$response = DB::table('ProductCatalog')\n    -\u003egetItem(['Id' =\u003e 101]);\n```\n\n\u003e Instead of marshaling manually, pass a plain array. `Kitar\\Dynamodb\\Query\\Grammar` will automatically marshal them before querying.\n\n#### putItem()\n\n```php\nDB::table('Thread')\n    -\u003eputItem([\n        'ForumName' =\u003e 'Amazon DynamoDB',\n        'Subject' =\u003e 'New discussion thread',\n        'Message' =\u003e 'First post in this thread',\n        'LastPostedBy' =\u003e 'fred@example.com',\n        'LastPostedDateTime' =\u003e '201603190422'\n    ]);\n```\n\n#### updateItem()\n\n```php\nDB::table('Thread')\n    -\u003ekey([\n        'ForumName' =\u003e 'Laravel',\n        'Subject' =\u003e 'Laravel Thread 1'\n    ])-\u003eupdateItem([\n        'LastPostedBy' =\u003e null, // REMOVE\n        'Replies' =\u003e null, // REMOVE\n        'Message' =\u003e 'Updated' // SET\n    ]);\n```\n\nCurrently, we only support simple `SET` and `REMOVE` actions. If the attribute has value, it will be passed to `SET` action. If the value is null, it will be passed to `REMOVE` action.\n\n#### deleteItem()\n\n```php\nDB::table('Thread')\n    -\u003edeleteItem([\n        'ForumName' =\u003e 'Amazon DynamoDB',\n        'Subject' =\u003e 'New discussion thread'\n    ]);\n```\n\n### Projection Expressions\n\nA Projection Expression is a string that identifies the attributes that web want. (It's like `select` statement for SQL)\n\n#### select()\n\nWe can specify Projection Expressions in the same manner as the original `select` clause.\n\n```php\n$response = DB::table('ProductCatalog')\n    -\u003eselect('Price', 'Title')\n    -\u003egetItem(['Id' =\u003e 101]);\n```\n\n### Condition Expressions\n\nWhen we manipulate data in Amazon DynamoDB table, we use `putItem`, `updateItem` and `DeleteItem`. We can use Condition Expressions to determine which items should be modified.\n\n#### condition()\n\nTo specify Condition Expression, we use `condition` clause. This works basically same as the original `where` clause, but it's for Condition Expressions.\n\n```php\nDB::table('ProductCatalog')\n    -\u003econdition('Id', 'attribute_not_exists')\n    -\u003eputItem([\n        'Id' =\u003e 101,\n        'ProductCategory' =\u003e 'Can I overwrite?'\n    ]);\n```\n\n\u003e Note that we specify `attribute_not_exists` for the operator of condition. This is DynamoDB-specific operator which called `function`. See [DynamoDB-specific operators for condition() and filter()](#dynamodb-specific-operators-for-condition-and-filter) for more details.\n\nOR statements\n\n```php\nDB::table('ProductCatalog')\n    -\u003econdition('Id', 'attribute_not_exists')\n    -\u003eorCondition('Price', 'attribute_not_exists)\n    -\u003eputItem([...]);\n```\n\nAND statements\n\n```php\nDB::table('ProductCatalog')\n    -\u003econdition('Id', 'attribute_not_exists')\n    -\u003econdition('Price', 'attribute_not_exists)\n    -\u003eputItem([...]);\n```\n\n#### conditionIn()\n\n```php\nProductCatalog::key(['Id' =\u003e 101])\n    -\u003econditionIn('ProductCategory', ['Book', 'Bicycle'])\n    -\u003eupdateItem([\n        'Description' =\u003e 'updated!'\n    ]);\n```\n\n#### conditionBetween()\n\n```php\nProductCatalog::key(['Id' =\u003e 101])\n    -\u003econditionBetween('Price', [0, 10])\n    -\u003eupdateItem([\n        'Description' =\u003e 'updated!'\n    ]);\n```\n\n### Working with Queries\n\nThe Query operation in Amazon DynamoDB finds items based on primary key values.\n\n#### query() and keyCondition()\n\nWhen we `query`, we must specify `keyCondition` as well.\n\nWe can use some comparison operators for sort key, but we must use the equality condition for the partition key.\n\n```php\n$response = DB::table('Thread')\n    -\u003ekeyCondition('ForumName', '=', 'Amazon DynamoDB')\n    -\u003ekeyCondition('Subject', 'begins_with', 'DynamoDB')\n    -\u003equery();\n```\n\n#### keyConditionBetween()\n\n```php\n$response = DB::table('Thread')\n    -\u003ekeyCondition('ForumName', '=', 'Amazon DynamoDB')\n    -\u003ekeyConditionBetween('Subject', ['DynamoDB Thread 1', 'DynamoDB Thread 2'])\n    -\u003equery();\n```\n\n#### Sort order\n\n`query` results are always sorted by the sort key value. To reverse the order, set the `ScanIndexForward` parameter to `false`.\n\n```php\n$response = DB::table('Thread')\n    -\u003ekeyCondition('ForumName', '=', 'Amazon DynamoDB')\n    -\u003escanIndexForward(false)\n    -\u003equery();\n```\n\n\u003e Note that DynamoDB's `ScanIndexForward` is a feature for `query`. It will not work with `scan`.\n\n### Working with Scans\n\n#### scan()\n\n```php\n$response = DB::table('Thread')-\u003escan();\n```\n\n### Filtering the Results\n\nWhen we `query` or `scan`, we can filter results with Filter Expressions before it returned.\n\nIt can't reduce the amount of read capacity, but it can reduce the size of traffic data.\n\n#### filter()\n\n```php\n$response = DB::table('Thread')\n    -\u003efilter('LastPostedBy', '=', 'User A')\n    -\u003escan();\n```\n\nOR statement\n\n```php\n$response = DB::table('Thread')\n    -\u003efilter('LastPostedBy', '=', 'User A')\n    -\u003eorFilter('LastPostedBy', '=', 'User B')\n    -\u003escan();\n```\n\nAND statement\n\n```php\n$response = DB::table('Thread')\n    -\u003efilter('LastPostedBy', '=', 'User A')\n    -\u003efilter('Subject', 'begins_with', 'DynamoDB')\n    -\u003escan();\n```\n\n#### filterIn()\n\n```php\n$response = DB::table('Thread')\n    -\u003efilterIn('LastPostedBy', ['User A', 'User B'])\n    -\u003escan();\n```\n\n#### filterBetween()\n\n```php\n$response = DB::table('ProductCatalog')\n    -\u003efilterBetween('Price', [0, 100])\n    -\u003escan();\n```\n\n### Paginating the Results\n\nA single `query` or `scan` only returns a result set that fits within the 1 MB size limit. If there are more results, we need to paginate.\n\n#### exclusiveStartKey()\n\nIf there are more results, the response contains `LastEvaluatedKey`.\n\n```php\n$response = DB::table('ProductCatalog')\n    -\u003elimit(5)\n    -\u003escan();\n\n$response['LastEvaluatedKey']; // array\n```\n\nWe can pass this key to `exclusiveStartKey` to get next results.\n\n```php\n$response = DB::table('ProductCatalog')\n    -\u003eexclusiveStartKey($response['LastEvaluatedKey'])\n    -\u003elimit(5)\n    -\u003escan();\n```\n\nIf you are using Query Builder through model, you can access to `exclusiveStartKey` by:\n\n```php\n$products = ProductCatalog::limit(5)-\u003escan();\n\n$products-\u003egetLastEvaluatedKey(); // array\n```\n\nAlternatively, you can achieve the same result using individual models; however, please be aware that this approach is planned to be deprecated in versions subsequent to v2.x.\n\n```php\n$products-\u003efirst()-\u003emeta()['LastEvaluatedKey']; // array\n```\n\n### Using Global Secondary Indexes\n\nSome applications might need to perform many kinds of queries, using a variety of different attributes as query criteria. To support these requirements, you can create one or more global secondary indexes and issue `query` requests against these indexes in Amazon DynamoDB.\n\n#### index()\n\nUse `index` clause to specify Global Secondary Index name.\n\n```php\n$response = DB::table('Reply')\n    -\u003eindex('PostedBy-Message-index')\n    -\u003ekeyCondition('PostedBy', '=', 'User A')\n    -\u003ekeyCondition('Message', '=', 'DynamoDB Thread 2 Reply 1 text')\n    -\u003equery();\n```\n\n### Atomic Counter\n\nDynamoDB [supports Atomic Counter](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.AtomicCounters). When we call `increment()` and `decrement()` [through Model](#increment--decrement) or Query Builder, Atomic Counter will be used under the hood.\n\n```php\nDB::('Thread')-\u003ekey([\n    'ForumName' =\u003e 'Laravel',\n    'Subject' =\u003e 'Laravel Thread 1'\n])-\u003eincrement('Replies', 2);\n```\n\nWe can also pass additional attributes to update.\n\n```php\nDB::('Thread')-\u003ekey([\n    'ForumName' =\u003e 'Laravel',\n    'Subject' =\u003e 'Laravel Thread 1'\n])-\u003eincrement('Replies', 2, [\n    'LastPostedBy' =\u003e 'User A',\n]);\n```\n\n### Batch Operations\n\nBatch operations can get, put or delete multiple items with a single call. There are some DynamoDB limitations (such as items count, payload size, etc), so please check the documentation in advance. ([BatchGetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html), [BatchWriteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html))\n\n#### batchGetItem()\n\n```php\nDB::table('Thread')\n    -\u003ebatchGetItem([\n        [\n            'ForumName' =\u003e 'Amazon DynamoDB',\n            'Subject' =\u003e 'DynamoDB Thread 1'\n        ],\n        [\n            'ForumName' =\u003e 'Amazon DynamoDB',\n            'Subject' =\u003e 'DynamoDB Thread 2'\n        ]\n    ]);\n```\n\n#### batchPutItem()\n\n```php\nDB::table('Thread')\n    -\u003ebatchPutItem([\n        [\n            'ForumName' =\u003e 'Amazon DynamoDB',\n            'Subject' =\u003e 'DynamoDB Thread 3'\n        ],\n        [\n            'ForumName' =\u003e 'Amazon DynamoDB',\n            'Subject' =\u003e 'DynamoDB Thread 4'\n        ]\n    ]);\n```\n\n\u003e This is a handy method to batch-put items using `batchWriteItem`\n\n#### batchDeleteItem()\n\n```php\nDB::table('Thread')\n    -\u003ebatchDeleteItem([\n        [\n            'ForumName' =\u003e 'Amazon DynamoDB',\n            'Subject' =\u003e 'DynamoDB Thread 1'\n        ],\n        [\n            'ForumName' =\u003e 'Amazon DynamoDB',\n            'Subject' =\u003e 'DynamoDB Thread 2'\n        ]\n    ]);\n```\n\n\u003e This is a handy method to batch-delete items using `batchWriteItem`\n\n#### batchWriteItem()\n\n```php\nDB::table('Thread')\n    -\u003ebatchWriteItem([\n        [\n            'PutRequest' =\u003e [\n                'Item' =\u003e [\n                    'ForumName' =\u003e 'Amazon DynamoDB',\n                    'Subject' =\u003e 'DynamoDB Thread 3'\n                ]\n            ]\n        ],\n        [\n            'DeleteRequest' =\u003e [\n                'Key' =\u003e [\n                    'ForumName' =\u003e 'Amazon DynamoDB',\n                    'Subject' =\u003e 'DynamoDB Thread 1'\n                ]\n            ]\n        ]\n    ]);\n```\n\n### DynamoDB-specific operators for condition() and filter()\n\nFor `condition` and `filter` clauses, we can use DynamoDB's comparators and functions.\n\n#### Comparators\n\n`=` `\u003c\u003e` `\u003c` `\u003c=` `\u003e` `\u003e=` can be used in the form of:\n\n```php\nfilter($key, $comparator, $value);\n```\n\n#### functions\n\nAvailable functions are:\n\n```php\nfilter($key, 'attribute_exists');\nfilter($key, 'attribute_not_exists');\nfilter($key, 'attribute_type', $type);\nfilter($key, 'begins_with', $value);\nfilter($key, 'contains', $value);\n```\n\n\u003e `size` function is not supported at this time.\n\n## Debugging\n\n#### dryRun()\n\nWe can inspect what parameters (and which method) will actually send to DynamoDB by adding `dryRun()` to our query. For example:\n\n```php\n// via Model\n$request = ProductCatalog::dryRun()-\u003egetItem(['Id' =\u003e 101]);\n\n// via Query Builder\n$request = DB::table('ProductCatalog')-\u003edryRun()-\u003egetItem(['Id' =\u003e 101]);\n\ndump($request);\n```\n\n\u003e Our PHPUnit tests also use this feature, without actually calling DynamoDB\n\n## Testing\n\n```\n$ ./vendor/bin/phpunit\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkitar%2Flaravel-dynamodb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkitar%2Flaravel-dynamodb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkitar%2Flaravel-dynamodb/lists"}