반응형
아래 코드 예제는 몽고디비에 loc 를 2D로 인덱스가 잡혀 있어야 한다.
또한 몽고DB의 다큐먼트에 loc 키값은 다음과 같은 배열로 되어있다고 가정. [lon, lat] 순서의 배열임.
그러면, nearSphere 를 통한 위치 검색이 가능하다.
결과 데이터는 JSON으로 인코딩하여 주는것으로 예제를 작성했음. (받는쪽에서는 디코딩하여 사용.)
입력은 위도, 경도, 거리(어느 거리까지 찾을 것인지) 를 셋팅해 주면 되고, $row_cnt와 $offset 으로 페이징 됨.
위도, 경도로 거리에 대한 미터(m), 킬로미터(km)를 가져오는 함수는 get_distance 함수를 사용하여 가져온다.
<?php
// 인풋데이터 셋팅하면 됨.
// $lat : 위도, $lon : 경도.
// $lat : 위도, $lon : 경도.
// $distance : 거리. 예) 15km, 30km
// $offset : 가져올 데이터의 시작점. 이는 한번에 15개씩 가져오고, 그 다음 15개씩 가져올때 사용함. 처음:0
// $offset : 가져올 데이터의 시작점. 이는 한번에 15개씩 가져오고, 그 다음 15개씩 가져올때 사용함. 처음:0
$row_cnt = 15;
// get_mongo_collection() 함수는 몽고디비에 접속하여 컬렉션을 반환하는 함수.
// 이는 구현하기 쉬우니 직접 구현하면 됩니다.
// 이는 구현하기 쉬우니 직접 구현하면 됩니다.
if(!$collection = get_mongo_collection()){
}
$radius = $distance/6378;
$loc = array($lon, $lat);
$query = array('loc'=>array('$nearSphere'=>$loc, '$maxDistance'=>$radius));
try{
$cursor = $collection->find($query)->limit($row_cnt)->skip($offset);
}
catch (MongoCursorException $e) {
}
$ret = iterator_to_array($cursor, false);
$i = 0;
foreach ($ret as $item){
$ret[$i]['_id'] = $item['_id']."";
$ret[$i]['lat'] = $item['loc'][1];
$ret[$i]['lon'] = $item['loc'][0];
$ret[$i]['distance'] = get_distance($lat, $lon, $item['loc'][1], $item['loc'][0], 'm');
$i++;
}
$result['err'] = 0;
$result['cnt'] = $cursor->count(true);
$result['ret'] = $ret;
echo json_encode($result);
// get distance by km or m or miles
function get_distance($lat1, $lon1, $lat2, $lon2, $unit) {
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
//$unit = strtoupper($unit);
// km
if ($unit == "k") {
return ($miles * 1.609344);
}
// m
else if ($unit == "m") {
return (int)($miles * 1.609344 * 1000);
}else if ($unit == "n") {
return ($miles * 0.8684);
}
// miles - M
else {
return $miles;
}
}
?>
반응형