1
|
|
|
<?php namespace Nord\Lumen\Elasticsearch\Search\Query\Geo; |
2
|
|
|
|
3
|
|
|
use Nord\Lumen\Elasticsearch\Exceptions\InvalidArgument; |
4
|
|
|
use Nord\Lumen\Elasticsearch\Search\Traits\HasField; |
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Filters documents that include only hits that exists within a specific distance from a geo point. |
8
|
|
|
* |
9
|
|
|
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-distance-query.html |
10
|
|
|
*/ |
11
|
|
|
class GeoDistanceQuery extends AbstractQuery |
12
|
|
|
{ |
13
|
|
|
use HasField; |
14
|
|
|
|
15
|
|
|
const DISTANCE_TYPE_SLOPPY_ARC = 'sloppy_arc'; |
16
|
|
|
const DISTANCE_TYPE_ARC = 'arc'; |
17
|
|
|
const DISTANCE_TYPE_PLANE = 'plane'; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @var mixed |
21
|
|
|
*/ |
22
|
|
|
private $latitude; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @var mixed |
26
|
|
|
*/ |
27
|
|
|
private $longitude; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var string The radius of the circle centred on the specified location. Points which fall into this circle are |
31
|
|
|
* considered to be matches. The distance can be specified in various units. |
32
|
|
|
* |
33
|
|
|
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#distance-units |
34
|
|
|
*/ |
35
|
|
|
private $distance; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var string How to compute the distance. Can either be sloppy_arc (default), arc (slightly more precise but |
39
|
|
|
* significantly slower) or plane (faster, but inaccurate on long distances and close to the poles). |
40
|
|
|
*/ |
41
|
|
|
private $distanceType; |
42
|
|
|
|
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @inheritdoc |
46
|
|
|
*/ |
47
|
|
|
public function toArray() |
48
|
|
|
{ |
49
|
|
|
$geoDistance = [ |
50
|
|
|
'distance' => $this->getDistance(), |
51
|
|
|
$this->getField() => [ |
52
|
|
|
'lat' => $this->getLatitude(), |
53
|
|
|
'lon' => $this->getLongitude(), |
54
|
|
|
] |
55
|
|
|
]; |
56
|
|
|
|
57
|
|
|
$distanceType = $this->getDistanceType(); |
58
|
|
|
if (!is_null($distanceType)) { |
59
|
|
|
$geoDistance['distance_type'] = $distanceType; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
return ['geo_distance' => $geoDistance]; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @param mixed $latitude |
68
|
|
|
* @param mixed $longitude |
69
|
|
|
* @return GeoDistanceQuery |
70
|
|
|
*/ |
71
|
|
|
public function setLocation($latitude, $longitude) |
72
|
|
|
{ |
73
|
|
|
$this->latitude = $latitude; |
74
|
|
|
$this->longitude = $longitude; |
75
|
|
|
return $this; |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* @return mixed |
81
|
|
|
*/ |
82
|
|
|
public function getLongitude() |
83
|
|
|
{ |
84
|
|
|
return $this->longitude; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @return mixed |
90
|
|
|
*/ |
91
|
|
|
public function getLatitude() |
92
|
|
|
{ |
93
|
|
|
return $this->latitude; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* @param string $distance |
99
|
|
|
* @return GeoDistanceQuery |
100
|
|
|
*/ |
101
|
|
|
public function setDistance($distance) |
102
|
|
|
{ |
103
|
|
|
$this->distance = $distance; |
104
|
|
|
return $this; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @return string |
110
|
|
|
*/ |
111
|
|
|
public function getDistance() |
112
|
|
|
{ |
113
|
|
|
return $this->distance; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* @param string $distanceType |
119
|
|
|
* @return GeoDistanceQuery |
120
|
|
|
* @throws InvalidArgument |
121
|
|
|
*/ |
122
|
|
|
public function setDistanceType($distanceType) |
123
|
|
|
{ |
124
|
|
|
$this->assertDistanceType($distanceType); |
125
|
|
|
$this->distanceType = $distanceType; |
126
|
|
|
return $this; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @return string |
132
|
|
|
*/ |
133
|
|
|
public function getDistanceType() |
134
|
|
|
{ |
135
|
|
|
return $this->distanceType; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @param string $distanceType |
141
|
|
|
* @throws InvalidArgument |
142
|
|
|
*/ |
143
|
|
View Code Duplication |
protected function assertDistanceType($distanceType) |
|
|
|
|
144
|
|
|
{ |
145
|
|
|
$validTypes = [self::DISTANCE_TYPE_SLOPPY_ARC, self::DISTANCE_TYPE_ARC, self::DISTANCE_TYPE_PLANE]; |
146
|
|
|
if (!in_array($distanceType, $validTypes)) { |
147
|
|
|
throw new InvalidArgument(sprintf( |
148
|
|
|
'GeoDistance Query `distance_type` must be one of "%s", "%s" given.', |
149
|
|
|
implode(', ', $validTypes), |
150
|
|
|
$distanceType |
151
|
|
|
)); |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
} |
155
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.