OVER_QUERY_LIMIT 응답을받지 않고 20 개 주소를 지오 코딩하려면 어떻게해야합니까?


87

Google Geocoder v3를 사용하여 20 개의 주소를 지오 코딩하려고하면 ~ 1 초 간격으로 시간을 설정하지 않으면 OVER_QUERY_LIMIT가 표시되지만 마커가 모두 배치되기까지 20 초가 걸립니다.

좌표를 미리 저장하는 것 외에 다른 방법이 있습니까?


이것이 여전히 사실입니까? 문서에서 볼 수있는 유일한 제한은 "하루에 2,500 개의 지리적 위치 요청 쿼리 제한"입니다. code.google.com/apis/maps/documentation/geocoding/…
russau

6
사용자 당 일일 총 쿼리 수가 아니라 루프에서 쿼리 할 때처럼 짧은 시간에 쿼리 수에 관한 것입니다.
Michiel van Oosterhout

우리 가게에 사업 허가증이 있는데 초당 10 건 이상의 요청을 처리 할 수 ​​없다는 문제가 여전히 발생합니다. 비즈니스 라이선스와 일반 개발자의 유일한 차이점은 하루에 100,000 개의 통화로 제한된다는 것입니다.
abhi

@michielvoo이 문제를 해결 했습니까? 그렇다면 친절하게 도와주세요. OVER_QUERY_LIMIT를 받고 있습니다. 그래서 내 질문 . 바이올린
Prabs

답변:


85

아니요, 다른 방법은 없습니다. 위치가 많고지도에 표시하려는 경우 가장 좋은 방법은 다음과 같습니다.

  • 위치가 생성 될 때 지오 코더를 사용하여 위도 + 경도를 가져옵니다.
  • 주소와 함께 데이터베이스에 저장
  • 지도를 표시하고 싶을 때 저장된 위도 + 경도를 사용합니다.

물론 이것은 위치에 대한 상담보다 위치 생성 / 수정이 훨씬 적다는 것을 고려할 때입니다.


예, 위치를 저장할 때 더 많은 작업을 수행해야하지만 다음을 의미합니다.

  • 지리적 좌표로 검색 할 수 있습니다.
    • 예 : " 지금 현재 위치에 가까운 지점 목록을 원합니다. "
  • 지도 표시가 훨씬 빨라집니다.
    • 20 개 이상의 위치가있는 경우에도
  • 아, 그리고 (마지막으로 중요한) : 이것은 작동합니다 ;-)
    • N 초 내에 X 지오 코더 호출 한도에 도달 할 가능성이 적습니다.
    • 그리고 하루에 Y 지오 코더 호출 한도에 도달 할 가능성이 적습니다.

일정 시간 (한 달)이 지난 후 결과가 올바른지 어떻게 확신 할 수 있는지 궁금합니다. 가끔씩 다시 쿼리합니까?
Chris

2
주소 (이미 DB에있는-그렇지 않으면 지오 코딩 할 수 없음 ) 가 변경되지 않으면 위도 / 경도가 변경 될 가능성이 매우 낮습니다. 물론 주소가 수정 될 때마다 지오 코더를 다시 쿼리하여 새 주소에 해당하는 위도 + 경도를 가져와야합니다.
Pascal MARTIN

위도 / 경도를 DB에 저장하고 AJAX를 통해 DB에서 배열로 검색했지만 Java 스크립트 루프로 다시 전달해야합니다. DB에서 173 개 위치를 더 많이 받았습니다. 이제 동일한 OVER_QUERY_LIMIT 상태가 표시됩니다. 조언 부탁드립니다 ...
Prabhu M

20

실제로 각 요청에 대해 1 초를 기다릴 필요가 없습니다. 각 요청 사이에 200 밀리 초를 기다리면 OVER_QUERY_LIMIT 응답을 피할 수 있고 사용자 경험이 통과 할 수 있다는 것을 알았습니다. 이 솔루션을 사용하면 4 초 내에 20 개의 항목을로드 할 수 있습니다.

$(items).each(function(i, item){

  setTimeout(function(){

    geoLocate("my address", function(myLatlng){
      ...
    });

  }, 200 * i);

}

5
그러나 (200 * i)는 각 요청 사이의 일시 중지가 증가하고 있음을 의미합니다. 따라서 세 번째 요청시 600, 800 등입니다.
Roman

바로 '* 나는'제거
크리스

9
setTimeout은 한 번 실행합니다. 따라서 내가 맞다면 (..., 200 * i) 각 통화를 200ms로 구분하여 예약합니다 (oyatek이 언급 한대로). 이것이 gabeodess가 달성하고자하는 것입니다. 전류 (..., 200)는 200ms 후에 모두 동시에 실행합니다. 아니면 내가 뭔가를 놓치고 있습니까?
레페

@gabeodess- setInterval대신 필요한 요청 수에 대해 수행해야하며 주소 금액이 나중에 언젠가 금액을 확장 할 경우를 대비하여로 setTimeout설정해야합니다 . 10020
Rob Scott

3
@gabeodess 난 당신의 솔루션을 시도했지만 여전히 OVER_QUERY_LIMIT 무엇입니까 바이올린
Prabs

6

안타깝게도 이것은 Google지도 서비스의 제한 사항입니다.

현재 지오 코딩 기능을 사용하는 응용 프로그램에서 작업 중이며 각 고유 주소를 사용자별로 저장하고 있습니다. Google지도에서 반환 한 정보를 기반으로 주소 정보 (시, 거리, 주 등)를 생성 한 다음 위도 / 경도 정보도 데이터베이스에 저장합니다. 이렇게하면 코드를 다시 코딩 할 필요가 없으며 멋진 형식의 주소를 얻을 수 있습니다.

이를 수행하려는 또 다른 이유는 특정 IP 주소에서 지오 코딩 할 수있는 주소 수에 일일 제한이 있기 때문입니다. 그런 이유로 신청이 실패하는 것을 원하지 않습니다.


2

140 개의 주소를 지오 코딩하려는 것과 동일한 문제에 직면 해 있습니다.

내 해결 방법은 다음 지오 코딩 요청의 각 루프에 대해 usleep (100000) 을 추가하는 것 입니다. 요청 상태가 OVER_QUERY_LIMIT이면 usleep이 50000 증가하고 요청이 반복됩니다.

그리고 수신 된 모든 데이터 (위도 / 경도)는 페이지가로드 될 때마다 요청을 실행하지 않도록 XML 파일에 저장됩니다.


1
귀하의 대답은 모호합니다. 서버 측에서 언급하고 있습니까? 아니면 자바 스크립트입니까? 후자의 경우 usleep은 기능 이 아니므 로 올바르지 않습니다. 전자라면 대답을 수정하여 명시 적으로 진술하는 것이 좋습니다. 모호함을 피하기 위해 서버 측입니다.
t0mm13b 2014

1

편집하다:

이 솔루션은 순수 JS에 말을 잊으, 당신이 필요로하는 유일한 것은 지원의 그 브라우저입니다 약속 https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Promise은


그래도이를 수행해야하는 사람들을 위해 약속과 시간 제한을 결합하는 자체 솔루션을 작성했습니다.

암호:

/*
    class: Geolocalizer
        - Handles location triangulation and calculations.
        -- Returns various prototypes to fetch position from strings or coords or dragons or whatever.
*/

var Geolocalizer = function () {
    this.queue          = [];     // queue handler..
    this.resolved       = [];
    this.geolocalizer = new google.maps.Geocoder();  
};

Geolocalizer.prototype = {
    /*
        @fn: Localize
        @scope: resolve single or multiple queued requests.
        @params: <array> needles
        @returns: <deferred> object
    */
    Localize: function ( needles ) {
        var that = this;
        // Enqueue the needles.
        for ( var i = 0; i < needles.length; i++ ) {
            this.queue.push(needles[i]);
        }
        // return a promise and resolve it after every element have been fetched (either with success or failure), then reset the queue.
        return new Promise (
            function (resolve, reject) {
                that.resolveQueueElements().then(function(resolved){
                  resolve(resolved);
                  that.queue    = [];
                  that.resolved = [];
                });
            }
        );
    },

    /*
        @fn: resolveQueueElements
        @scope: resolve queue elements.
        @returns: <deferred> object (promise)
    */

    resolveQueueElements: function (callback) {
        var that = this;
        return new Promise(
            function(resolve, reject) {
                // Loop the queue and resolve each element.
                // Prevent QUERY_LIMIT by delaying actions by one second.
                (function loopWithDelay(such, queue, i){
                    console.log("Attempting the resolution of " +queue[i-1]);
                    setTimeout(function(){
                        such.find(queue[i-1], function(res){
                           such.resolved.push(res); 
                        });
                        if (--i) {
                            loopWithDelay(such,queue,i);
                        }
                    }, 1000);
                })(that, that.queue, that.queue.length);

                // Check every second if the queue has been cleared.
                var it = setInterval(function(){
                    if (that.queue.length == that.resolved.length) {
                        resolve(that.resolved);
                        clearInterval(it);
                    }
                }, 1000);
            }
        );
    },

    /*
        @fn: find
        @scope: resolve an address from string
        @params: <string> s, <fn> Callback
    */
    find: function (s, callback) {
        this.geolocalizer.geocode({
            "address": s
        }, function(res, status){
           if (status == google.maps.GeocoderStatus.OK) {
               var r = {
                   originalString:  s,
                   lat: res[0].geometry.location.lat(),
                   lng: res[0].geometry.location.lng()
               };
               callback(r);
           }
            else {
                callback(undefined);
                console.log(status);
                console.log("could not locate " + s);
            }
        });
    }
};

Google지도를 처리하기 위해 작성한 더 큰 라이브러리의 일부일 뿐이므로 댓글이 혼란 스러울 수 있습니다.

사용법은 매우 간단하지만 접근 방식은 약간 다릅니다. 한 번에 하나의 주소를 반복하고 확인하는 대신 클래스에 주소 배열을 전달해야하며 검색을 자체적으로 처리하여 약속을 반환합니다. , 확인되면 확인 된 (및 확인되지 않은) 주소를 모두 포함하는 배열을 반환합니다.

예:

var myAmazingGeo = new Geolocalizer();
var locations = ["Italy","California","Dragons are thugs...","China","Georgia"];
myAmazingGeo.Localize(locations).then(function(res){ 
   console.log(res); 
});

콘솔 출력 :

Attempting the resolution of Georgia
Attempting the resolution of China
Attempting the resolution of Dragons are thugs...
Attempting the resolution of California
ZERO_RESULTS
could not locate Dragons are thugs...
Attempting the resolution of Italy

반환 된 개체 :

여기에 이미지 설명 입력

모든 마법이 여기에서 발생합니다.

(function loopWithDelay(such, queue, i){
                    console.log("Attempting the resolution of " +queue[i-1]);
                    setTimeout(function(){
                        such.find(queue[i-1], function(res){
                           such.resolved.push(res); 
                        });
                        if (--i) {
                            loopWithDelay(such,queue,i);
                    }
                }, 750);
            })(that, that.queue, that.queue.length);

기본적으로 각 항목간에 750 밀리 초의 지연으로 모든 항목을 반복하므로 750 밀리 초마다 주소가 제어됩니다.

몇 가지 추가 테스트를 수행 한 결과 700 밀리 초에서도 가끔 QUERY_LIMIT 오류가 발생하는 반면 750에서는 전혀 문제가 없다는 것을 알았습니다.

어쨌든 더 낮은 지연을 처리하여 안전하다고 생각되면 위의 750을 자유롭게 편집하십시오.

이것이 가까운 장래에 누군가에게 도움이되기를 바랍니다.)


0

방금 Google Geocoder를 테스트했으며 귀하와 동일한 문제가 발생했습니다. 12 개의 요청에 한 번만 OVER_QUERY_LIMIT 상태를 얻는다는 것을 알아 챘습니다. 그래서 1 초 동안 기다립니다 (즉, 대기하는 최소 지연입니다). 애플리케이션 속도가 느려지지만 모든 요청을 기다리는 시간은 1 초 미만입니다.

info = getInfos(getLatLng(code)); //In here I call Google API
record(code, info);
generated++; 
if(generated%interval == 0) {
holdOn(delay); // Every x requests, I sleep for 1 second
}

기본 holdOn 방법 :

private void holdOn(long delay) {
        try {
            Thread.sleep(delay);
        } catch (InterruptedException ex) {
            // ignore
        }
    }

도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.