%PDF- %PDF-
| Direktori : /home/graphicd/public_html/vebto/vendor/teamtnt/tntsearch/src/ |
| Current File : /home/graphicd/public_html/vebto/vendor/teamtnt/tntsearch/src/TNTGeoSearch.php |
<?php
namespace TeamTNT\TNTSearch;
use PDO;
use TeamTNT\TNTSearch\Indexer\TNTGeoIndexer;
use TeamTNT\TNTSearch\Support\Collection;
class TNTGeoSearch extends TNTSearch
{
protected $earthRadius = 6371;
/**
* Distance is in KM
*/
public function findNearest($currentLocation, $distance, $limit = 10)
{
$startTimer = microtime(true);
$res = $this->buildQuery($currentLocation, $distance, $limit);
$stopTimer = microtime(true);
return [
'ids' => $res->pluck('doc_id'),
'distances' => $res->pluck('distance'),
'hits' => $res->count(),
'execution_time' => round($stopTimer - $startTimer, 7) * 1000 ." ms"
];
}
public function buildQuery($currentLocation, $distance, $limit)
{
$query = "
SELECT doc_id, longitude, latitude,
:CUR_sin_lat * sin_lat + :CUR_cos_lat * cos_lat * (cos_lng * :CUR_cos_lng + sin_lng * :CUR_sin_lng) AS distance
FROM locations AS l
JOIN (
SELECT :latpoint AS latpoint, :longpoint AS longpoint,
:radius AS radius, 111.045 AS distance_unit
) AS p
WHERE l.latitude
BETWEEN p.latpoint - (p.radius / p.distance_unit)
AND p.latpoint + (p.radius / p.distance_unit)
AND l.longitude
BETWEEN p.longpoint - (p.radius / (p.distance_unit * :CUR_cos_lat))
AND p.longpoint + (p.radius / (p.distance_unit * :CUR_cos_lat))
ORDER BY distance DESC
LIMIT :limit";
$stmtDoc = $this->index->prepare($query);
$cur_lat = $currentLocation['latitude'];
$cur_lng = $currentLocation['longitude'];
$CUR_cos_lat = cos($cur_lat * pi() / 180);
$CUR_sin_lat = sin($cur_lat * pi() / 180);
$CUR_cos_lng = cos($cur_lng * pi() / 180);
$CUR_sin_lng = sin($cur_lng * pi() / 180);
$stmtDoc->bindValue(':latpoint', $cur_lat);
$stmtDoc->bindValue(':longpoint', $cur_lng);
$stmtDoc->bindValue(':radius', $distance);
$stmtDoc->bindValue(':CUR_cos_lat', $CUR_cos_lat);
$stmtDoc->bindValue(':CUR_sin_lat', $CUR_sin_lat);
$stmtDoc->bindValue(':CUR_cos_lng', $CUR_cos_lng);
$stmtDoc->bindValue(':CUR_sin_lng', $CUR_sin_lng);
$stmtDoc->bindValue(':limit', $limit);
$stmtDoc->execute();
$locations = new Collection($stmtDoc->fetchAll(PDO::FETCH_ASSOC));
$locations = $locations->map(function ($location) use ($distance) {
$location['distance'] = acos($location['distance']) * $this->earthRadius;
if ($location['distance'] <= $distance) {
return $location;
}
});
return $locations;
}
public function getIndex()
{
$indexer = new TNTGeoIndexer;
$indexer->inMemory = false;
$indexer->setIndex($this->index);
return $indexer;
}
}