Skip to content

Commit 2c7c599

Browse files
committed
Order by Geo, order By Nested & Nested Queries
1 parent 414817f commit 2c7c599

File tree

5 files changed

+212
-3
lines changed

5 files changed

+212
-3
lines changed

src/DSL/Bridge.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,6 @@ private function _queryTag($function)
828828

829829
private function _sanitizeSearchResponse($response, $params, $queryTag)
830830
{
831-
832831
$meta['timed_out'] = $response['timed_out'];
833832
$meta['total'] = $response['hits']['total']['value'] ?? 0;
834833
$meta['max_score'] = $response['hits']['max_score'] ?? 0;
@@ -844,20 +843,45 @@ private function _sanitizeSearchResponse($response, $params, $queryTag)
844843
$datum[$key] = $value;
845844
}
846845
}
846+
if (!empty($hit['inner_hits'])) {
847+
foreach ($hit['inner_hits'] as $innerKey => $innerHit) {
848+
$datum[$innerKey] = $this->_filterInnerHits($innerHit);
849+
}
850+
}
851+
847852
//------------------------ later, maybe ------------------------------
848853
// if (!empty($hit['sort'])) {
849854
// $datum['_meta']['sort'] = $this->_parseSort($hit['sort'], $params['body']['sort'] ?? []);
850855
// }
851856
//----------------------------------------------------------------------
852857

853858

854-
$data[] = $datum;
859+
{
860+
$data[] = $datum;
861+
}
855862
}
856863
}
857864

858865
return $this->_return($data, $meta, $params, $queryTag);
859866
}
860867

868+
private function _filterInnerHits($innerHit)
869+
{
870+
$hits = [];
871+
foreach ($innerHit['hits']['hits'] as $inner) {
872+
$innerDatum = [];
873+
if (!empty($inner['_source'])) {
874+
foreach ($inner['_source'] as $innerSourceKey => $innerSourceValue) {
875+
$innerDatum[$innerSourceKey] = $innerSourceValue;
876+
}
877+
}
878+
$hits[] = $innerDatum;
879+
}
880+
881+
return $hits;
882+
}
883+
884+
861885
private function _parseSort($sort, $sortParams)
862886
{
863887
$sortValues = [];

src/DSL/ParameterBuilder.php

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ public static function query($dsl): array
3535

3636
public static function fieldSort($field, $payload): array
3737
{
38-
38+
if (!empty($payload['is_geo'])) {
39+
return self::fieldSortGeo($field, $payload);
40+
}
41+
if (!empty($payload['is_nested'])) {
42+
return self::filterNested($field, $payload);
43+
}
3944
$sort = [];
4045
$sort['order'] = $payload['order'] ?? 'asc';
4146
if (!empty($payload['mode'])) {
@@ -50,6 +55,43 @@ public static function fieldSort($field, $payload): array
5055
];
5156
}
5257

58+
public static function fieldSortGeo($field, $payload): array
59+
{
60+
$sort = [];
61+
$sort[$field] = $payload['pin'];
62+
$sort['order'] = $payload['order'] ?? 'asc';
63+
$sort['unit'] = $payload['unit'] ?? 'km';
64+
65+
if (!empty($payload['mode'])) {
66+
$sort['mode'] = $payload['mode'];
67+
}
68+
if (!empty($payload['type'])) {
69+
$sort['distance_type'] = $payload['type'];
70+
}
71+
72+
return [
73+
'_geo_distance' => $sort,
74+
];
75+
}
76+
77+
public static function filterNested($field, $payload)
78+
{
79+
$sort = [];
80+
$pathParts = explode('.', $field);
81+
$path = $pathParts[0];
82+
$sort['order'] = $payload['order'] ?? 'asc';
83+
if (!empty($payload['mode'])) {
84+
$sort['mode'] = $payload['mode'];
85+
}
86+
$sort['nested'] = [
87+
'path' => $path,
88+
];
89+
90+
91+
return [
92+
$field => $sort,
93+
];
94+
}
5395

5496
public static function maxAggregation($field): array
5597
{

src/DSL/QueryBuilder.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,21 @@ private function _parseCondition($condition, $parentField = null): array
370370
],
371371

372372
];
373+
break;
374+
case 'innerNested':
375+
$options = $this->_buildNestedOptions($operand['options'], $field);
376+
$query = ParameterBuilder::matchAll()['query'];
377+
if (!empty($operand['wheres'])) {
378+
$query = $this->_convertWheresToDSL($operand['wheres'], $field);
379+
}
380+
$queryPart = [
381+
'nested' => [
382+
'path' => $field,
383+
'query' => $query,
384+
'inner_hits' => $options,
385+
],
386+
];
387+
373388
break;
374389
default:
375390
abort('400', 'Invalid operator ['.$operator.'] provided for condition.');
@@ -425,6 +440,32 @@ private function _buildOptions($options): array
425440
return $return;
426441
}
427442

443+
private function _buildNestedOptions($options, $field)
444+
{
445+
$options = $this->_buildOptions($options);
446+
if (!empty($options['body'])) {
447+
$body = $options['body'];
448+
unset($options['body']);
449+
$options = array_merge($options, $body);
450+
}
451+
if (!empty($options['sort'])) {
452+
//ensure that the sort field is prefixed with the nested field
453+
$sorts = [];
454+
foreach ($options['sort'] as $sort) {
455+
foreach ($sort as $sortField => $sortPayload) {
456+
if (!str_starts_with($sortField, $field.'.')) {
457+
$sortField = $field.'.'.$sortField;
458+
}
459+
$sorts[] = [$sortField => $sortPayload];
460+
}
461+
}
462+
463+
$options['sort'] = $sorts;
464+
}
465+
466+
return $options;
467+
}
468+
428469
public function _parseFilter($filterType, $filterPayload): void
429470
{
430471
switch ($filterType) {

src/Eloquent/Docs/ModelDocs.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
* @method $this firstOrCreateWithoutRefresh(array $attributes, array $values = [])
3232
* @method $this orderBy(string $column, string $direction = 'asc', string $mode = null, array $missing = '_last')
3333
* @method $this orderByDesc(string $column, string $mode = null, array $missing = '_last')
34+
* @method $this orderByGeo(string $column, array $pin, $direction = 'asc', $unit = 'km', $mode = null, $type = 'arc')
35+
* @method $this orderByGeoDesc(string $column, array $pin, $unit = 'km', $mode = null, $type = 'arc')
36+
* @method $this orderByNested(string $column, string $direction = 'asc', string $mode = null)
37+
*
38+
* @method $this queryNested(string $column, Callable $callback)
39+
*
3440
* @method $this deleteIndexIfExists()
3541
*
3642
*

src/Query/Builder.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,31 @@ public function whereExact($column, $value)
364364
}
365365

366366

367+
/**
368+
* @param $column
369+
* @param $callBack
370+
*
371+
* @return $this
372+
*/
373+
public function queryNested($column, $callBack)
374+
{
375+
$boolean = 'and';
376+
$query = $this->newQuery();
377+
$callBack($query);
378+
$wheres = $query->compileWheres();
379+
$options = $query->compileOptions();
380+
$this->wheres[] = [
381+
'column' => $column,
382+
'type' => 'QueryNested',
383+
'wheres' => $wheres,
384+
'options' => $options,
385+
'boolean' => $boolean,
386+
];
387+
388+
return $this;
389+
}
390+
391+
367392
//----------------------------------------------------------------------
368393
// Query Processing (Connection API)
369394
//----------------------------------------------------------------------
@@ -544,6 +569,65 @@ public function orderByDesc($column, $mode = null, $missing = null)
544569
return $this->orderBy($column, 'desc', $mode, $missing);
545570
}
546571

572+
/**
573+
* @param $column
574+
* @param $pin
575+
* @param $direction @values: 'asc', 'desc'
576+
* @param $unit @values: 'km', 'mi', 'm', 'ft'
577+
* @param $mode @values: 'min', 'max', 'avg', 'sum'
578+
* @param $type @values: 'arc', 'plane'
579+
*
580+
* @return $this
581+
*/
582+
public function orderByGeo($column, $pin, $direction = 'asc', $unit = 'km', $mode = null, $type = null)
583+
{
584+
$this->orders[$column] = [
585+
'is_geo' => true,
586+
'order' => $direction,
587+
'pin' => $pin,
588+
'unit' => $unit,
589+
'mode' => $mode,
590+
'type' => $type,
591+
];
592+
593+
return $this;
594+
}
595+
596+
/**
597+
* @param $column
598+
* @param $pin
599+
* @param $unit @values: 'km', 'mi', 'm', 'ft'
600+
* @param $mode @values: 'min', 'max', 'avg', 'sum'
601+
* @param $type @values: 'arc', 'plane'
602+
*
603+
* @return $this
604+
*/
605+
public function orderByGeoDesc($column, $pin, $unit = 'km', $mode = null, $type = null)
606+
{
607+
return $this->orderByGeo($column, $pin, 'desc', $unit, $mode, $type);
608+
}
609+
610+
611+
/**
612+
* @param $column
613+
* @param $direction
614+
* @param $mode
615+
*
616+
* @return $this
617+
*/
618+
public function orderByNested($column, $direction = 'asc', $mode = null)
619+
{
620+
$this->orders[$column] = [
621+
'is_nested' => true,
622+
'order' => $direction,
623+
'mode' => $mode,
624+
625+
];
626+
627+
return $this;
628+
}
629+
630+
547631
/**
548632
* @inheritdoc
549633
*/
@@ -843,6 +927,18 @@ protected function _parseWhereNested(array $where)
843927

844928
}
845929

930+
protected function _parseWhereQueryNested(array $where)
931+
{
932+
return [
933+
$where['column'] => [
934+
'innerNested' => [
935+
'wheres' => $where['wheres'],
936+
'options' => $where['options'],
937+
],
938+
],
939+
];
940+
}
941+
846942
/**
847943
* @param array $where
848944
*

0 commit comments

Comments
 (0)