ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [MongoDB] 8. 몽고DB와 PHP로 위치 인식 웹 애플리케이션 제작
    CSE/MongoDB 2015. 6. 13. 11:50

    이번 장은 요즘 핫한!!! 위치 기반의 서비스를 만들어 보도록 하겠습니다!!!

    순서는 아래와 같습니다.
     1. W3C API로 위치 파악
     2. 지리 공간 색인 생성
     3. 현재 위치에 가까운 음식점 찾기
     4. 버거를 판매하는 근처 음식점 찾기






    1. W3C API로 위치 파악하기

    이번 실습에서, 지리 공간 API를 사용하여 방문객의 위치를 파악하는 웹페이지를 구축하도록 하겠습니다. 

    먼저 location.html을 작성해주세요!

    location.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <link rel="stylesheet" href="style.css"/>
            <style type="text/css" media="screen">
    div#map {
    width: 450px;
    height: 400px;
    }
    </style>
            <title> Locating your position </title>
        </head>
        <body>
            <div id="contentarea">
                <div id="innercontentarea">
                    <h2> Locating your position </h2>
                    <div id="map"></div>
                </div>
            </div>
            <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
            <script type="text/javascript" src="geolocation.js"></script>
        </body>
    </html>
     
    cs





    다음 geolocation.js를 작성합니다.

    geolocation.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    var mapContainer = document.getElementById('map');
    var map;
     
    function init() {
        // Google Map Set(축척, 지도 유형 등)
        var mapOptions = { 
            zoom: 16,
            disableDefaultUI: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        
        // 지도는 mapContainer 내부에 mapOptions으로 그려짐
        map = new google.maps.Map(mapContainer, mapOptions);
        detectLocation();
    }
     
    function detectLocation() {
        var options = {
            enableHighAccuracy: true,
            maximumAge: 1000,
            timeout: 30000
        };
        
        // 브라우저가 Geolocation 객체를 지원하는지 check
        if (window.navigator.geolocation) {
            window.navigator.geolocation.getCurrentPosition(
                drawLocationOnMap,
                handleGeolocateError,
                options
            );
        } else {
            alert("Sorry, your browser doesn't seem to support geolocation :-(");
        }
    }
     
    // getCurrentPosition()의 콜백함수로 구글 맵에 위치를 찍음
    function drawLocationOnMap(position) {
        // Position 객체에서 위도 / 경도 얻기
        var lat = position.coords.latitude;
        var lon = position.coords.longitude;
        var msg = "You ar here: Latitude +" + lat + ", Longitude " + lon;
        
        var pos = new google.maps.LatLng(lat, lon);
        var infoBox = new google.maps.InfoWindow({
            map: map,
            position: pos,
            content: msg
        });
        
        map.setCenter(pos);
        
        return;
    }
     
    function handleGeolocateError() {
        alert("Sorry, couldn't get your geolocation: -(");
    }
     
    window.onload = init;
    cs




    브라우저에서 location.html을 열어주세요. 열어주면, 위치 접근 허가를 묻는데 허용을 해야 어플리케이션이 구동되는지 알수 있겠죠?? 
    아래와 같이 결과가 나온답니다~




     





    이번 장의 구현된 객체 등에 대해 설명하겠습니다.

     Geolocation 객체
      - 이 객체는 W3C 지리 공간 API를 구현합니다. 
         JS 엔진은 이 객체를 사용해 브라우저가 동작 중인 컴퓨터나 전화의 지리 공간 정보를 얻습니다. 
         Geolocation은 브라우저 객체(window.navigator)의 속성이며, window.navigator.geolocation으로 접근합니다. 
         이번 예제에서 Geolocation 객체에 접근하는 방법으로 브라우저에 지리 공간 기능이 있는지 검사하고,, 브라우저가 테스트에 실패하면 이를 사용자에게 통지하도록 구축했습니다.


     - getCurrentPosition() 메소드: 객체에 존재하는 getCurrentPosition() 메소드를 호출하는 방법으로 위치 정보를 얻습니다.
      쓰임새는 다음과 같습니다.

       getCurrentPosition(callbackOnSuccess, [callbackOnFailure, options])

      callbackOnSuccess 인수는 콜백 함수를 참조합니다. 이 콜백 함수는 getCurrentPosition() 메소드가 성공적으로 지리 좌표를 파악할 때 호출됩니다. 
      callbackOnFailure는 선택 옵션이며, 지리 공간을 얻는 데 실패할 경우 처리하기 위한 콜백 함수입니다.
      options는 추가적인 메소드에 대한 구성 매개변수를 지정하는 PositionOptions 객체를 표현합니다.
     
      PositionOptions에는 다음과 같은 속성이 있고, 저희는 이 속성을 건드렸죠~
        · enableHighAccuracy: API에게 정확한 현재 위치를 얻기 위해 최선을 다하도록 요청합니다. 기본값은 false로 설정되어 있습니다. true로 설정할 때, API반응이 느려지는 경향이 있습니다.
        · maximumAge: API 반응을 캐시하는 경우에, 이 설정값은 maximumAge 밀리초보다 오래된 캐시값을 사용하지 않도록 지정합니다.
        · timeout: API응답을 받기 위해 밀리초 단위로 지정한 타임아웃 값입니다.








    2. 지리 공간 색인 생성하기


    몽고 쉘을 열어서 아래와 같이 작성해주세요~ 빨간색으로 체크된 부분만 작성해주시면 됩니다~







      
    위 작업에 대해 보충 설명을 하자면, map이라는 데이터베이스에 geocollection이라는 몽고 DB Collection을 만들었습니다. 수동으로 컬렉션에 다큐먼트를 삽입했고, 다큐먼트마다 들어있는 coordinate라는 내장된 다큐먼트는 임의로 설정한 latitude와 longitude 값을 포함합니다. 
     그러고 나서, 해당 컬렉션에 대해 ensureIndex()를 호출하여 latitude/longitude 쌍에 대한 지리 공간 색인(Index)를 구축했습니다.






    3. 현재 위치에 가까운 음식점 찾기
     다음으로 색인이 걸린 필드를 대상으로 위치 질의를 수행하는 방법을 배울 시간입니다~ 
     먼저, restaurants라는 컬렉션으로 몇 가지 데이터를 삽입합니다~

     db.restaurants.insert({name:"McDowells", serves: "Fast Food", "location": [23.755235, 90.375739]})
     db.restaurants.insert({name:"Bucksters Coffee", serves: "Fast Food", "location": [23.755339, 90.375408]})
     db.restaurants.insert({name:"Dinkin Donuts", serves: "Fast Food", "location": [23.752538, 90.382792]})

    그러고 나서, 지리 공간 색인을 구축합니다.
     
     db.restaurants.ensureIndex({location:"2d"})


     




    다음으로 restaurants.html을 작성합니다.

    restaurants.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <link rel="stylesheet" href="style.css"/>
            <style type="text/css" media="screen">
                div#map {
                    width: 450px;
                    height: 400px;
                }
            </style>
            <title> Restaurants near me </title>
        </head>
        <body>
            <div id="contentarea">
                <div id="innercontentarea">
                    <h2> Restaurants near me </h2>
                    <div id="map"></div>
                    <br />
                </div>
            </div>
            <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
            <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
            <script type="text/javascript" src="restaurants.js"></script>
        </body>
    </html>
     
    cs

     





    다음으로 restaurants.js를 작성합니다

    restaurants.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
     
    var mapContainer = document.getElementById('map');
    var map;
     
    function init() {
        // Google Map Set(축척, 지도 유형 등)
        var mapOptions = { 
            zoom: 14,
            disableDefaultUI: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        
        // 지도는 mapContainer 내부에 mapOptions으로 그려짐
        map = new google.maps.Map(mapContainer, mapOptions);
        detectLocation();
    }
     
    function detectLocation() {
        var options = {
            enableHighAccuracy: true,
            maximumAge: 1000,
            timeout: 30000
        };
        
        // 브라우저가 Geolocation 객체를 지원하는지 check
        if (window.navigator.geolocation) {
            window.navigator.geolocation.getCurrentPosition(
                markMyLocation,
                handleGeolocateError,
                options
            );
        } else {
            alert("Sorry, your browser doesn't seem to support geolocation :-(");
        }
    }
     
    function markMyLocation(position) {
        // Position 객체에서 위도 / 경도 얻기
        var lat = position.coords.latitude; 
        var lon = position.coords.longitude;
        var msg = "You are here";
        
        var pos = new google.maps.LatLng(lat, lon);
        
        map.setCenter(pos);
        
        var infoBox = new google.maps.InfoWindow({
            map: map,
            position: pos,
            content: msg
        });
        
        // 현재 위치 구글 맵 표식 그리기
        var myMarker = new google.maps.Marker({
            map: map,
            position: pos
        });
        
        getNearByRestaurants(lat, lon);
        
        return;
    }
     
    function handleGeolocateError() {
        alert("Sorry, couldn't get your geolocation: -(");
    }
     
    function getNearByRestaurants(lat, lon) {
        $.ajax({
            url: 'query.php?lat=' + lat + '&lon=' + lon
            , dataType: 'json'
            , success: ajaxSuccess
        });
    }
     
    // AJAX 를 위한 콜백 함수
    function ajaxSuccess(data) {
        data.forEach(function(restaurant) {
            var pos = new google.maps.LatLng(restaurant.latitude, restaurant.longitude);
            var marker = new google.maps.Marker({
                map: map,
                position: pos
            });
        });
    }
     
    window.onload = init;
    cs




    마지막으로 query.php

    query.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?php
    $lat = (float) $_GET['lat'];
    $lon = (float) $_GET['lon'];
     
    $mongo = new Mongo();
    $collection = $mongo->selectDB('geolocation')->selectCollection('restaurants');
     
    $query = array(
    'location' => array('$near' => array($lat$lon))
    );
     
    $cursor = $collection->find($query);
    $response = array();
     
    while ($doc = $cursor->getNext()) {
    $obj = array(
    'name' => $doc['name'],
    'serves' => $doc['serves'],
    'latitude' => $doc['location'][0],
    'longitude' => $doc['location'][1]
    );
    array_push($response$obj);
    }
     
    echo json_encode($response);
    ?>
    cs




     

    요렇게 작성하고 실행해주시면!!!!! 각자의 위치와 함께 식당이 떠야되는데.... 되는데... 식당은 안뜨고... you are here 만 떳네요...


     





    아무래도 몽고DB에 넣은 위치값은 저멀리 있었나 봅니다.... 방글라데시에 있네요....






     






    4. 버거(Fast Food)를 판매하는 근처 음식점 찾기
    이번에는 지리 공간 헤이스택 색인을 사용하여 버거를 판매하는 곳을 찾아보겠습니다. 

    수행에 앞서, 저는 저희 동네 버거 집을 물색하여 insert해놨습니다.

    그럼 진행 하도록 하겠습니다.

    몽고 쉘에서  
     db.restaurants.ensureIndex({location:"geoHaystack", serves:1}, {bucketSize: 1})

     입력하세요~
     

    다음으로 haystack.html을 작성합니다.

    haystack.html

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <link rel="stylesheet" href="style.css"/>
            <style type="text/css" media="screen">
    div#map {
    width: 450px;
    height: 400px;
    }
    </style>
            <title> Burger place near me </title>
        </head>
        <body>
            <div id="contentarea">
                <div id="innercontentarea">
                    <h2> Burger place near me </h2>
                    <div id="map"></div>
                    <br />
                </div>
            </div>
            <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
            <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
            <script type="text/javascript" src="haystack.js"></script>
        </body>
    </html>
     
    cs





    haystack.js


     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
     
    var mapContainer = document.getElementById('map');
    var map;
     
    function init() {
        // Google Map Set(축척, 지도 유형 등)
        var mapOptions = { 
            zoom: 15,
            disableDefaultUI: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        
        // 지도는 mapContainer 내부에 mapOptions으로 그려짐
        map = new google.maps.Map(mapContainer, mapOptions);
        detectLocation();
    }
     
    function detectLocation() {
        var options = {
            enableHighAccuracy: true,
            maximumAge: 1000,
            timeout: 30000
        };
        
        // 브라우저가 Geolocation 객체를 지원하는지 check
        if (window.navigator.geolocation) {
            window.navigator.geolocation.getCurrentPosition(
                markMyLocation,
                handleGeolocateError,
                options
            );
        } else {
            alert("Sorry, your browser doesn't seem to support geolocation :-(");
        }
    }
     
    function markMyLocation(position) {
        // Position 객체에서 위도 / 경도 얻기
        var lat = position.coords.latitude; 
        var lon = position.coords.longitude;
        var msg = "You are here";
        
        var pos = new google.maps.LatLng(lat, lon);
        
        map.setCenter(pos);
        
        var infoBox = new google.maps.InfoWindow({
            map: map,
            position: pos,
            content: msg
        });
        
        // 현재 위치 구글 맵 표식 그리기
        var myMarker = new google.maps.Marker({
            map: map,
            position: pos
        });
        
        getNearByRestaurants(lat, lon);
        
        return;
    }
     
    function handleGeolocateError() {
        alert("Sorry, couldn't get your geolocation: -(");
    }
     
    function getNearByRestaurants(lat, lon) {
        $.ajax({
            url: 'haystack.php?lat=' + lat + '&lon=' + lon
            , dataType: 'json'
            , success: ajaxSuccess
        });
    }
     
    // AJAX 를 위한 콜백 함수
    function ajaxSuccess(data) {
        data.forEach(function(restaurant) {
            var pos = new google.maps.LatLng(restaurant.latitude, restaurant.longitude);
            var marker = new google.maps.Marker({
                map: map,
                position: pos
            });
            var infoBox = new google.maps.InfoWindow({
                map: map,
                position: pos,
                content: restaurant.name
            });
        });
    }
     
    window.onload = init;
    cs





    haystack.php

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <?php
    $lat = (float) $_GET['lat'];
    $lon = (float) $_GET['lon'];
     
    $mongo = new Mongo();
    $db = $mongo->selectDB('geolocation');
     
    $command = array(
    'geoSearch' => 'restaurants',
    'near' => array($lat$lon),
    'search' => array('serves' => 'Fast Food'),
    'maxDistance' => 10
    );
     
    $response = $db->command($command);
    $jsonResponse = array();
     
    foreach ($response['results'as $result) {
    $obj = array(
    'name' => $result['name'],
    'serves' => $result['serves'],
    'latitude' => $result['location'][0],
    'longitude' => $result['location'][1]
    );
     
    array_push($jsonResponse$obj);
    }
     
    echo json_encode($jsonResponse);
     
    ?>
    cs





    이렇게 하고 실행하면!!!






    요렇게 나오네요~

    네. 이상으로 이번 장 포스팅을 마치겠습니다~







    댓글

Designed by Tistory.