Skip to content

Commit c79bd63

Browse files
authored
Add limit support (#76)
Close #73
1 parent 1643c50 commit c79bd63

File tree

4 files changed

+74
-6
lines changed

4 files changed

+74
-6
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ $model->chunk(10, function ($records) {
112112
113113
}
114114
});
115+
116+
// limit
117+
// Use this with caution unless your limit is small.
118+
// DynamoDB has a limit of 1MB so if your limit is very big, the results will not be expected.
119+
$model->where('name', 'foo')->take(3)->get();
115120
```
116121
117122
* Or if you want to sync your DB table with a DynamoDb table, use trait `BaoPham\DynamoDb\ModelTrait`, it will call a `PutItem` after the model is saved.

src/DynamoDbQueryBuilder.php

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99

1010
class DynamoDbQueryBuilder
1111
{
12+
/**
13+
* The maximum number of records to return.
14+
*
15+
* @var int
16+
*/
17+
public $limit;
18+
1219
/**
1320
* @var array
1421
*/
@@ -33,6 +40,30 @@ class DynamoDbQueryBuilder
3340
*/
3441
protected $lastEvaluatedKey;
3542

43+
/**
44+
* Alias to set the "limit" value of the query.
45+
*
46+
* @param int $value
47+
* @return DynamoDbQueryBuilder\static
48+
*/
49+
public function take($value)
50+
{
51+
return $this->limit($value);
52+
}
53+
54+
/**
55+
* Set the "limit" value of the query.
56+
*
57+
* @param int $value
58+
* @return $this
59+
*/
60+
public function limit($value)
61+
{
62+
$this->limit = $value;
63+
64+
return $this;
65+
}
66+
3667
public function where($column, $operator = null, $value = null, $boolean = 'and')
3768
{
3869
if ($boolean != 'and') {
@@ -209,6 +240,10 @@ public function count()
209240

210241
protected function getAll($columns = [], $limit = -1, $use_iterator = true)
211242
{
243+
if ($limit === -1 && isset($this->limit)) {
244+
$limit = $this->limit;
245+
}
246+
212247
if ($conditionValue = $this->conditionsContainKey()) {
213248
if ($this->conditionsAreExactSearch()) {
214249
$item = $this->find($conditionValue, $columns);
@@ -237,14 +272,14 @@ protected function getAll($columns = [], $limit = -1, $use_iterator = true)
237272

238273
// If the $where is not empty, we run getIterator.
239274
if (!empty($this->where)) {
240-
241275
// Index key condition exists, then use Query instead of Scan.
242276
// However, Query only supports a few conditions.
243277
if ($index = $this->conditionsContainIndexKey()) {
244278
$keysInfo = $index['keysInfo'];
245279
$isCompositeKey = isset($keysInfo['range']);
246280
$hashKeyOperator = array_get($this->where, $keysInfo['hash'] . '.ComparisonOperator');
247281
$isValidQueryDynamoDbOperator = ComparisonOperator::isValidQueryDynamoDbOperator($hashKeyOperator);
282+
248283
if ($isValidQueryDynamoDbOperator && $isCompositeKey) {
249284
$rangeKeyOperator = array_get($this->where, $keysInfo['range'] . '.ComparisonOperator');
250285
$isValidQueryDynamoDbOperator = ComparisonOperator::isValidQueryDynamoDbOperator($rangeKeyOperator, true);
@@ -254,10 +289,13 @@ protected function getAll($columns = [], $limit = -1, $use_iterator = true)
254289
$op = 'Query';
255290
$query['IndexName'] = $index['name'];
256291
$query['KeyConditions'][$keysInfo['hash']] = array_get($this->where, $keysInfo['hash']);
292+
257293
if ($isCompositeKey) {
258294
$query['KeyConditions'][$keysInfo['range']] = array_get($this->where, $keysInfo['range']);
259295
}
296+
260297
$nonKeyConditions = array_except($this->where, array_values($keysInfo));
298+
261299
if (!empty($nonKeyConditions)) {
262300
$query['QueryFilter'] = $nonKeyConditions;
263301
}
@@ -274,6 +312,10 @@ protected function getAll($columns = [], $limit = -1, $use_iterator = true)
274312

275313
if ($use_iterator) {
276314
$iterator = $this->client->getIterator($op, $query);
315+
316+
if (isset($query['Limit'])) {
317+
$iterator = new \LimitIterator($iterator, 0, $query['Limit']);
318+
}
277319
} else {
278320
if ($op === 'Scan') {
279321
$res = $this->client->scan($query);

tests/DynamoDbCompositeModelTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public function testStaticMethods()
185185

186186
public function testConditionContainingCompositeIndexKey()
187187
{
188-
$fooItem = $this->seed([
188+
$this->seed([
189189
'id' => ['S' => 'id1'],
190190
'id2' => ['S' => '2'],
191191
'name' => ['S' => 'Foo'],
@@ -234,7 +234,7 @@ public function testConditionContainingCompositeIndexKey()
234234

235235
public function testConditionsDoNotContainAllCompositeKeys()
236236
{
237-
$fooItem = $this->seed([
237+
$this->seed([
238238
'id' => ['S' => 'id1'],
239239
'id2' => ['S' => '2'],
240240
'name' => ['S' => 'Foo'],

tests/DynamoDbModelTest.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public function testDifferentQueries()
318318
$barQuery = $this->testModel->where('name', 'Bar');
319319

320320
$this->assertEquals(1, $fooQuery->count());
321-
$this->assertEquals(1, $fooQuery->count());
321+
$this->assertEquals(1, $barQuery->count());
322322
$this->assertEquals($this->testModel->unmarshalItem($expectedFoo), $fooQuery->first()->toArray());
323323
$this->assertEquals($this->testModel->unmarshalItem($expectedBar), $barQuery->first()->toArray());
324324
}
@@ -332,9 +332,9 @@ public function testChunkScan()
332332
$iteration = 1;
333333

334334
$this->testModel->chunk(2, function ($results) use (&$iteration) {
335-
if ($iteration == 1) {
335+
if ($iteration === 1) {
336336
$this->assertEquals(2, count($results));
337-
} else if ($iteration == 2) {
337+
} else if ($iteration === 2) {
338338
$this->assertEquals(1, count($results));
339339
}
340340

@@ -415,6 +415,27 @@ public function testSerialize()
415415
$this->assertInstanceOf(get_class($this->testModel), $unserializedItems->first());
416416
}
417417

418+
public function testLimit()
419+
{
420+
$count = 10;
421+
for ($i = 0; $i < $count; $i++) {
422+
$this->seed(['name' => ['S' => 'foo']]);
423+
}
424+
425+
$items = $this->testModel->take(3)->get();
426+
$this->assertCount(3, $items->toArray());
427+
428+
$items = $this->testModel->limit(3)->get();
429+
$this->assertCount(3, $items->toArray());
430+
431+
// Ensure "limit" is reset in new queries
432+
$items = $this->testModel->get();
433+
$this->assertCount($count, $items->toArray());
434+
435+
$items = $this->testModel->where('name', 'foo')->take(4)->get();
436+
$this->assertCount(4, $items->toArray());
437+
}
438+
418439
protected function seed($attributes = [])
419440
{
420441
$item = [

0 commit comments

Comments
 (0)