Skip to content

Commit 16c5399

Browse files
committed
add batch write and read support
1 parent ea7001f commit 16c5399

File tree

14 files changed

+752
-11
lines changed

14 files changed

+752
-11
lines changed

src/Contracts/BatchRequest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Mehedi\LaravelDynamoDB\Contracts;
4+
5+
interface BatchRequest
6+
{
7+
public function toArray() : array;
8+
}

src/Eloquent/Builder.php

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Builder
4646
* @var string[]
4747
*/
4848
protected $passthru = [
49-
'toArray', 'insert'
49+
'toArray', 'insert', 'putItemBatch', 'deleteItemBatch'
5050
];
5151

5252
public function __construct(QueryBuilder $query)
@@ -113,6 +113,89 @@ public function first(array $columns = ['*'], string $mode = FetchMode::QUERY):
113113
return is_null($item) ? null : $this->model->newFromBuilder($item);
114114
}
115115

116+
/**
117+
* Get the first record matching the attributes or create it.
118+
*
119+
* @param array|string $key
120+
* @param array $values
121+
* @return Model
122+
*/
123+
public function firstOrCreate($key, array $values = []): Model
124+
{
125+
$model = $this->firstOrNew($key, $values);
126+
127+
if ($model->exists) {
128+
return $model;
129+
}
130+
131+
$model->save();
132+
133+
return $model;
134+
}
135+
136+
/**
137+
* Get the first record matching the attributes or instantiate it.
138+
*
139+
* @param array $key
140+
* @param array $values
141+
* @return Model
142+
*/
143+
public function firstOrNew(array $key, array $values = [])
144+
{
145+
$model = $this->find($key);
146+
147+
return is_null($model) ? $this->newModelInstance($values)->setKey($key) : $model;
148+
}
149+
150+
/**
151+
* Create or update a record matching the attributes, and fill it with values.
152+
*
153+
* @param array $key
154+
* @param array $values
155+
* @return Model
156+
*/
157+
public function updateOrCreate(array $key, array $values = [])
158+
{
159+
$model = $this->firstOrNew($key, $values);
160+
161+
$model->exists ? $model->update($values) : $model->save();
162+
163+
return $model;
164+
}
165+
166+
/**
167+
* Alias of getItemBatch
168+
*
169+
* @param $keys
170+
* @param int $chunkSize
171+
* @alias getItemBatch()
172+
* @return \Illuminate\Support\Collection
173+
*/
174+
public function findMany($keys, int $chunkSize = 100)
175+
{
176+
return $this->getItemBatch($keys, $chunkSize);
177+
}
178+
179+
/**
180+
* Find many models in a single request
181+
*
182+
* @param $keys
183+
* @param int $chunkSize
184+
* @return \Illuminate\Support\Collection
185+
*/
186+
public function getItemBatch($keys, int $chunkSize = 100)
187+
{
188+
$primaryKey = $this->model->getKeysName();
189+
190+
$keys = array_map(function ($key) use ($primaryKey) {
191+
return array_combine($primaryKey, $key);
192+
}, $keys);
193+
194+
return $this->query->getItemBatch($keys, $chunkSize)->transform(function ($item) {
195+
return $this->model->newFromBuilder($item);
196+
});
197+
}
198+
116199
/**
117200
* Query items from database using query mode
118201
*
@@ -160,9 +243,9 @@ protected function checkFetchMode($mode)
160243
* Save a new model and return the instance.
161244
*
162245
* @param array $attributes
163-
* @return Model|$this
246+
* @return Model
164247
*/
165-
public function create(array $attributes = [])
248+
public function create(array $attributes = []): Model
166249
{
167250
return tap($this->newModelInstance($attributes), function (Model $instance) {
168251
$instance->save();
@@ -191,7 +274,6 @@ public function update(array $values, string $returnValues = ReturnValues::NONE)
191274
return $this->query->update($values);
192275
}
193276

194-
195277
/**
196278
* Query items from database using scan mode
197279
*
@@ -213,7 +295,7 @@ public function scan($columns = [])
213295
* Create a new instance of the model being queried.
214296
*
215297
* @param array $attributes
216-
* @return \Illuminate\Database\Eloquent\Model|static
298+
* @return Model
217299
*/
218300
public function newModelInstance(array $attributes = [])
219301
{

src/Eloquent/Model.php

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Mehedi\LaravelDynamoDB\Eloquent;
44

55
use Illuminate\Database\Eloquent\Model as BaseModel;
6+
use Illuminate\Support\Arr;
7+
use Illuminate\Support\Collection;
68
use Mehedi\LaravelDynamoDB\Collections\ItemCollection;
79

810
/**
@@ -14,6 +16,13 @@
1416
* @method static Model find($key, $column = [])
1517
* @method static Model findOrFail($key, $column = [])
1618
* @method static Model create(array $attributes)
19+
* @method static Model firstOrCreate(array $key, $values = [])
20+
* @method static Model firstOrNew(array $key, $values = [])
21+
* @method static Model updateOrCreate(array $key, $values = [])
22+
* @method static array putItemBatch(array $items, $chunkSize = 25)
23+
* @method static array deleteItemBatch(array $keys, $chunkSize = 25)
24+
* @method static Collection getItemBatch(array $keys, $chunkSize = 25)
25+
* @method static Collection findMany(array $keys, $chunkSize = 25)
1726
*
1827
* @see \Mehedi\LaravelDynamoDB\Eloquent\Builder
1928
*/
@@ -252,7 +261,7 @@ protected function updatePerform($query)
252261
*/
253262
protected function setKeysForSaveQuery($query): Builder
254263
{
255-
$key = (array) $this->getKey();
264+
$key = $this->getKey();
256265

257266
$query->key(...array_values($key));
258267

@@ -292,6 +301,54 @@ public function refresh()
292301
return $this;
293302
}
294303

304+
/**
305+
* Clone the model into a new, non-existing instance.
306+
*
307+
* @param array|null $except
308+
* @return Model
309+
*/
310+
public function replicate(array $except = null)
311+
{
312+
$replicate = parent::replicate($except);
313+
314+
if ($this->sortKey) {
315+
Arr::forget($replicate->attributes, $this->sortKey);
316+
}
317+
318+
return $replicate;
319+
}
320+
321+
/**
322+
* Set key on the model instance
323+
*
324+
* @param $key
325+
* @return Model
326+
*/
327+
public function setKey($key)
328+
{
329+
$key = (array) $key;
330+
331+
$this->attributes += $this->key(...$key)->query->key;
332+
333+
return $this;
334+
}
335+
336+
/**
337+
* Get only keys name
338+
*
339+
* @return array
340+
*/
341+
public function getKeysName()
342+
{
343+
$primaryKey = [$this->getKeyName()];
344+
345+
if ($sortKey = $this->getSortKeyName()) {
346+
$primaryKey[] = $sortKey;
347+
}
348+
349+
return $primaryKey;
350+
}
351+
295352

296353
/**
297354
* Handle dynamic method calls into the model.

src/Query/Batch/DeleteRequest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
namespace Mehedi\LaravelDynamoDB\Query\Batch;
3+
4+
use Mehedi\LaravelDynamoDB\Contracts\BatchRequest;
5+
use Mehedi\LaravelDynamoDB\Utils\Marshaler;
6+
7+
class DeleteRequest implements BatchRequest
8+
{
9+
/**
10+
* @var array
11+
*/
12+
protected $key;
13+
14+
public function __construct($key)
15+
{
16+
$this->key = $key;
17+
}
18+
19+
/**
20+
* Processed request payload
21+
*
22+
* @return array
23+
*/
24+
public function toArray() : array
25+
{
26+
return [
27+
'Key' => Marshaler::marshalItem($this->key)
28+
];
29+
}
30+
31+
/**
32+
* Make an instance of PutRequest
33+
*
34+
* @param $key
35+
* @return DeleteRequest
36+
*/
37+
public static function make($key) : DeleteRequest
38+
{
39+
return new self($key);
40+
}
41+
}

src/Query/Batch/Get.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
namespace Mehedi\LaravelDynamoDB\Query\Batch;
4+
5+
class Get
6+
{
7+
/**
8+
* @var array $keys
9+
*/
10+
protected $keys = [];
11+
12+
/**
13+
* Make an instance of Get class
14+
*
15+
* @return Get
16+
*/
17+
public static function make()
18+
{
19+
return new self();
20+
}
21+
22+
/**
23+
* Add a single key
24+
*
25+
* @param $table
26+
* @param $key
27+
* @return $this
28+
*/
29+
public function add($table, $key)
30+
{
31+
$this->makeTableSpace($table);
32+
33+
$this->keys[$table][] = $key;
34+
35+
return $this;
36+
}
37+
38+
/**
39+
* Add multiple keys
40+
*
41+
* @param $table
42+
* @param $keys
43+
* @return $this
44+
*/
45+
public function addMany($table, $keys)
46+
{
47+
$this->makeTableSpace($table);
48+
49+
$this->keys[$table] += $keys;
50+
51+
return $this;
52+
}
53+
54+
/**
55+
* Add an array inside of table name key
56+
*
57+
* @param $table
58+
*/
59+
public function makeTableSpace($table)
60+
{
61+
if (! array_key_exists($table, $this->keys)) {
62+
$this->keys[$table] = [];
63+
}
64+
}
65+
66+
/**
67+
* Get keys
68+
*
69+
* @return array
70+
*/
71+
public function keys()
72+
{
73+
return $this->keys;
74+
}
75+
}

src/Query/Batch/PutRequest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
namespace Mehedi\LaravelDynamoDB\Query\Batch;
3+
4+
use Mehedi\LaravelDynamoDB\Contracts\BatchRequest;
5+
use Mehedi\LaravelDynamoDB\Utils\Marshaler;
6+
7+
class PutRequest implements BatchRequest
8+
{
9+
/**
10+
* @var array
11+
*/
12+
protected $item;
13+
14+
public function __construct($item)
15+
{
16+
$this->item = $item;
17+
}
18+
19+
/**
20+
* Processed request payload
21+
*
22+
* @return array
23+
*/
24+
public function toArray() : array
25+
{
26+
return [
27+
'Item' => Marshaler::marshalItem($this->item)
28+
];
29+
}
30+
31+
/**
32+
* Make an instance of PutRequest
33+
*
34+
* @param $item
35+
* @return PutRequest
36+
*/
37+
public static function make($item) : PutRequest
38+
{
39+
return new self($item);
40+
}
41+
}

0 commit comments

Comments
 (0)