MongoDB

MongoDB PHP 위치기반 검색하기

macro 2011. 11. 10. 17:13
반응형

아래 코드 예제는 몽고디비에 loc 를 2D로 인덱스가 잡혀 있어야 한다. 

또한 몽고DB의 다큐먼트에 loc 키값은 다음과 같은 배열로 되어있다고 가정. [lon, lat] 순서의 배열임.

그러면, nearSphere 를 통한 위치 검색이 가능하다. 

결과 데이터는 JSON으로 인코딩하여 주는것으로 예제를 작성했음. (받는쪽에서는 디코딩하여 사용.)

입력은 위도, 경도, 거리(어느 거리까지 찾을 것인지) 를 셋팅해 주면 되고, $row_cnt와 $offset 으로 페이징 됨.

위도, 경도로 거리에 대한 미터(m), 킬로미터(km)를 가져오는 함수는 get_distance 함수를 사용하여 가져온다.


<?php

// 인풋데이터 셋팅하면 됨.
        // $lat : 위도,   $lon : 경도.
// $distance : 거리.  예) 15km, 30km 
        // $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;
}
}

?>

반응형