Skip to content

Commit 0cd5ed3

Browse files
author
Olek Kaim
committed
dev release 1.3.0
1 parent 62e8254 commit 0cd5ed3

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed

src/Builder/Builder.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,26 @@ class Builder implements BuilderInterface
2020
{
2121
use Conditionable;
2222

23+
public const ORDER_DESC = 'desc';
24+
25+
public const ORDER_ASC = 'asc';
26+
27+
public const ORDER_MIN_MODE = 'min';
28+
29+
public const ORDER_MAX_MODE = 'max';
30+
31+
public const ORDER_SUM_MODE = 'sum';
32+
33+
public const ORDER_AVG_MODE = 'avg';
34+
35+
public const ORDER_MEDIAN_MODE = 'median';
36+
2337
private string $index;
2438

2539
private array $query;
2640

41+
private array $sort;
42+
2743
private array $body = [];
2844

2945
public function __construct(private readonly ClientInterface $client)
@@ -145,6 +161,58 @@ public function whereRange(string $field, int|float $value, string $operator): s
145161
return $this;
146162
}
147163

164+
/**
165+
* @throws LogicException
166+
*/
167+
public function orderBy(string $field, string $direction = self::ORDER_DESC, ?string $mode = null): self
168+
{
169+
if ($direction !== self::ORDER_DESC && $direction !== self::ORDER_ASC) {
170+
throw new LogicException(
171+
sprintf(
172+
'Available direction values [%s, %s]. Entered value: [%s]',
173+
self::ORDER_DESC,
174+
self::ORDER_ASC,
175+
$direction,
176+
)
177+
);
178+
}
179+
180+
$order = match (true) {
181+
!is_null($mode) => function () use ($mode, $field, $direction): void {
182+
$availableValues = [
183+
self::ORDER_MIN_MODE,
184+
self::ORDER_MAX_MODE,
185+
self::ORDER_SUM_MODE,
186+
self::ORDER_AVG_MODE,
187+
self::ORDER_MEDIAN_MODE,
188+
];
189+
190+
if (!in_array($mode, $availableValues)) {
191+
throw new LogicException(
192+
sprintf(
193+
'Available direction values [%s, %s, %s, %s, %s]. Entered value: [%s]',
194+
self::ORDER_MIN_MODE,
195+
self::ORDER_MAX_MODE,
196+
self::ORDER_SUM_MODE,
197+
self::ORDER_AVG_MODE,
198+
self::ORDER_MEDIAN_MODE,
199+
$mode,
200+
)
201+
);
202+
}
203+
204+
$this->sort[][$field] = ['order' => $direction, 'mode' => $mode];
205+
},
206+
is_null($mode) => function () use ($field, $direction): void {
207+
$this->sort[][$field] = $direction;
208+
}
209+
};
210+
211+
$order();
212+
213+
return $this;
214+
}
215+
148216
public function offset(int $offset): self
149217
{
150218
$this->body['from'] = $offset;
@@ -159,6 +227,20 @@ public function limit(int $limit): self
159227
return $this;
160228
}
161229

230+
public function rawQuery(array $query): self
231+
{
232+
$this->query = $query;
233+
234+
return $this;
235+
}
236+
237+
public function rawSort(array $sort): self
238+
{
239+
$this->sort = $sort;
240+
241+
return $this;
242+
}
243+
162244
/**
163245
* @throws IndexNotFoundResponseException
164246
* @throws FindResponseException
@@ -247,6 +329,11 @@ public function getQuery(): array
247329
return $this->query;
248330
}
249331

332+
public function getSort(): array
333+
{
334+
return $this->sort;
335+
}
336+
250337
private function performSearchBody(): void
251338
{
252339
if (isset($this->query)) {

src/Contracts/BuilderInterface.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Olekjs\Elasticsearch\Contracts;
44

5+
use LogicException;
56
use Olekjs\Elasticsearch\Builder\Builder;
67
use Olekjs\Elasticsearch\Dto\FindResponseDto;
78
use Olekjs\Elasticsearch\Dto\PaginateResponseDto;
@@ -14,6 +15,8 @@
1415

1516
interface BuilderInterface
1617
{
18+
public const ORDER_DESC = 'desc';
19+
1720
public static function query(?ClientInterface $client = null): Builder;
1821

1922
public function index(string $index): self;
@@ -34,6 +37,10 @@ public function whereLike(string $field, string|int|float|array $value): self;
3437

3538
public function orWhereLike(string $field, string|int|float|array $value): self;
3639

40+
public function whereNot(string $field, string|int|float|array $value): self;
41+
42+
public function orWhereNot(string $field, string|int|float|array $value): self;
43+
3744
public function whereGreaterThan(string $field, int|float $value): self;
3845

3946
public function whereLessThan(string $field, int|float $value): self;
@@ -42,10 +49,19 @@ public function whereBetween(string $field, array $values): self;
4249

4350
public function whereRange(string $field, int|float $value, string $operator): self;
4451

52+
/**
53+
* @throws LogicException
54+
*/
55+
public function orderBy(string $field, string $direction = self::ORDER_DESC, ?string $mode = null): self;
56+
4557
public function offset(int $offset): self;
4658

4759
public function limit(int $limit): self;
4860

61+
public function rawQuery(array $query): self;
62+
63+
public function rawSort(array $sort): self;
64+
4965
/**
5066
* @throws IndexNotFoundResponseException
5167
* @throws FindResponseException
@@ -81,4 +97,6 @@ public function getIndex(): string;
8197
public function getBody(): array;
8298

8399
public function getQuery(): array;
100+
101+
public function getSort(): array;
84102
}

tests/Unit/BuilderTest.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,97 @@ public function testOrWhereNotMethod(): void
400400
'bool' => ['should' => [['bool' => ['must_not' => [['term' => ['name' => 'test']]]]]]]
401401
], $builder->getQuery());
402402
}
403+
404+
public function testOrderByMethod(): void
405+
{
406+
$builder = Builder::query()->orderBy('name', Builder::ORDER_ASC);
407+
408+
$this->assertSame([
409+
['name' => Builder::ORDER_ASC]
410+
], $builder->getSort());
411+
412+
$builder->orderBy('surname');
413+
414+
$this->assertSame([
415+
['name' => Builder::ORDER_ASC],
416+
['surname' => Builder::ORDER_DESC],
417+
], $builder->getSort());
418+
}
419+
420+
public function testOrderByWithModeMethod(): void
421+
{
422+
$builder = Builder::query()->orderBy('name', Builder::ORDER_ASC, Builder::ORDER_AVG_MODE);
423+
424+
$this->assertSame([
425+
['name' => ['order' => Builder::ORDER_ASC, 'mode' => Builder::ORDER_AVG_MODE]]
426+
], $builder->getSort());
427+
428+
$builder->orderBy('price', Builder::ORDER_DESC, Builder::ORDER_MIN_MODE);
429+
430+
$this->assertSame([
431+
['name' => ['order' => Builder::ORDER_ASC, 'mode' => Builder::ORDER_AVG_MODE]],
432+
['price' => ['order' => Builder::ORDER_DESC, 'mode' => Builder::ORDER_MIN_MODE]],
433+
], $builder->getSort());
434+
}
435+
436+
public function testOrderByWithInvalidDirectionMethod(): void
437+
{
438+
$errorMessage = sprintf(
439+
'Available direction values [%s, %s]. Entered value: [ascc]',
440+
Builder::ORDER_DESC,
441+
Builder::ORDER_ASC,
442+
);
443+
444+
$this->expectException(LogicException::class);
445+
$this->expectExceptionMessage($errorMessage);
446+
447+
Builder::query()->orderBy('name', 'ascc');
448+
}
449+
450+
public function testOrderByWithInvalidModeMethod(): void
451+
{
452+
$mode = 'not-exist';
453+
454+
$errorMessage = sprintf(
455+
'Available direction values [%s, %s, %s, %s, %s]. Entered value: [%s]',
456+
Builder::ORDER_MIN_MODE,
457+
Builder::ORDER_MAX_MODE,
458+
Builder::ORDER_SUM_MODE,
459+
Builder::ORDER_AVG_MODE,
460+
Builder::ORDER_MEDIAN_MODE,
461+
$mode,
462+
);
463+
464+
$this->expectException(LogicException::class);
465+
$this->expectExceptionMessage($errorMessage);
466+
467+
Builder::query()->orderBy('name', Builder::ORDER_DESC, $mode);
468+
}
469+
470+
public function testRawQueryMethod(): void
471+
{
472+
$query = [
473+
'query' => [
474+
'match_all' => (object)[]
475+
]
476+
];
477+
478+
$builder = Builder::query()->rawQuery($query);
479+
480+
$this->assertSame($query, $builder->getQuery());
481+
}
482+
483+
public function testRawSortMethod(): void
484+
{
485+
$sort = [
486+
'name' => [
487+
'order' => Builder::ORDER_DESC,
488+
'mode' => Builder::ORDER_MIN_MODE
489+
]
490+
];
491+
492+
$builder = Builder::query()->rawSort($sort);
493+
494+
$this->assertSame($sort, $builder->getSort());
495+
}
403496
}

0 commit comments

Comments
 (0)