Unikasz limitu geokodów w Mapach Google?

32

Tworzę niestandardową mapę Google, która ma 125 znaczników wykreślonych za pomocą cms. Podczas ładowania mapy otrzymuję ten komunikat:

Geokod nie powiódł się z następującego powodu: OVER_QUERY_LIMIT

Jestem prawie pewien, że w ten sposób geokodowałem znaczniki.

Jak mogę uniknąć tych ostrzeżeń i czy istnieje bardziej skuteczny sposób geokodowania wyników?

AKTUALIZACJA: To jest moja próba odpowiedzi Casey, właśnie dostaję pustą stronę.

<script type="text/javascript"> 
(function() { 

window.onload = function() { 
 var mc;
// Creating an object literal containing the properties we want to pass to the map 
var options = { 
zoom: 10, 
center: new google.maps.LatLng(52.40, -3.61), 
mapTypeId: google.maps.MapTypeId.ROADMAP 
}; 

// Creating the map 
var map = new google.maps.Map(document.getElementById('map'), options); 

// Creating a LatLngBounds object 
var bounds = new google.maps.LatLngBounds(); 

// Creating an array that will contain the addresses 
var places = []; 

// Creating a variable that will hold the InfoWindow object 
var infowindow; 
mc = new MarkerClusterer(map);
<?php
$pages = get_pages(array('child_of' => $post->ID, 'sort_column' => 'menu_order'));
$popup_content = array();
foreach($pages as $post)
    {
    setup_postdata($post);
    $fields = get_fields(); 
    $popup_content[] = '<p>'.$fields->company_name.'</p><img src="'.$fields->company_logo.'" /><br /><br /><a href="'.get_page_link($post->ID).'">View profile</a>';
    $comma = ", ";
    $full_address = "{$fields->address_line_1}{$comma}{$fields->address_line_2}{$comma}{$fields->address_line_3}{$comma}{$fields->post_code}";
    $address[] = $full_address;
    }
wp_reset_query();
echo 'var popup_content = ' . json_encode($popup_content) . ';';
echo 'var address = ' . json_encode($address) . ';';
?>

var geocoder = new google.maps.Geocoder(); 

var markers = [];

// Adding a LatLng object for each city  
for (var i = 0; i < address.length; i++) { 
    (function(i) { 
        geocoder.geocode( {'address': address[i]}, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                places[i] = results[0].geometry.location;

                // Adding the markers 
                var marker = new google.maps.Marker({position: places[i], map: map});
                markers.push(marker);
                mc.addMarker(marker);

                // Creating the event listener. It now has access to the values of i and marker as they were during its creation
                google.maps.event.addListener(marker, 'click', function() {
                    // Check to see if we already have an InfoWindow
                    if (!infowindow) {
                        infowindow = new google.maps.InfoWindow();
                    }

                    // Setting the content of the InfoWindow
                    infowindow.setContent(popup_content[i]);

                    // Tying the InfoWindow to the marker 
                    infowindow.open(map, marker);
                });

                // Extending the bounds object with each LatLng 
                bounds.extend(places[i]); 

                // Adjusting the map to new bounding box 
                map.fitBounds(bounds) 
            } else { 
            alert("Geocode was not successful for the following reason: " + status); 
            }

        });

    })(i);

} 
var markerCluster = new MarkerClusterer(map, markers); 
} 
})
(); 
</script> 

Tak naprawdę nie ma znaczenia, jakie jest rozwiązanie, o ile markery ładują się natychmiast i nie łamie żadnych warunków.

Obrabować
źródło
Nie mów dlaczego ani jak często przeprowadzasz te wyszukiwania. Nie próbujesz geokodować tych samych punktów na każdej renderowanej stronie, prawda? W takim przypadku powinieneś rozważyć użycie interfejsu API, aby wykonać te wyszukiwania po stronie serwera tylko raz, gdy lokalizacja jest dodawana do bazy danych po raz pierwszy.
Piotra,
Jeśli chcesz spróbować @ radą Piotra, jest prostym narzędziem tutaj które Geokodując punkty w arkuszu kalkulacyjnym Google. Umożliwiłoby to zapisanie długości / długości geograficznej dla miast w CMS, więc nie trzeba używać geokodera w czasie wykonywania.
Stephen Lead
@Peter Właściwie to brzmi jak świetny pomysł. Jestem trochę rozdarty, ponieważ zmniejszy to użyteczność moich cms. Jeśli klient musi dowiedzieć się o długości / długości każdej firmy, a nie tylko o podaniu adresu, nie jest to zbyt przyjazne dla użytkownika. Czy rozumiem to poprawnie?
Rob
Zobacz moją nową odpowiedź niżej dla funkcji php.
Peter,
2
@rob FWIW Myślę, że Ragi ma właściwe podejście. Odpowiedź Caseya nadal wymaga geokodowania każdego punktu, za każdym razem, gdy rysuje mapa, co nie wydaje się konieczne dla twojego statycznego zestawu danych
Stephen Lead

Odpowiedzi:

57

Jak wszyscy inni, mógłbym dać ci odpowiedź z kodem, ale nie sądzę, żeby ktoś ci wytłumaczył, że robisz coś, co jest zasadniczo złe .

Dlaczego napotykasz ten błąd? Ponieważ wywołujesz geokod za każdym razem, gdy ktoś przegląda twoją stronę i nie zapisujesz wyników w pamięci podręcznej nigdzie!

Limit istnieje, aby zapobiegać nadużyciom ze strony zasobów Google (czy to dobrowolnie, czy niechętnie) - właśnie to robisz :)

Chociaż geokod Google'a jest szybki, gdyby wszyscy tak go używali, spowodowałoby to awarię serwerów. Powodem, dla którego istnieją tabele Google Fusion, jest wykonywanie dużych obciążeń po stronie serwera. Geokodowanie i buforowanie kafelków odbywa się na ich serwerach. Jeśli nie chcesz tego używać, powinieneś buforować je na swoim serwerze.

Jeśli nadal 2500 żądań dziennie to za mało, musisz spojrzeć na licencję Google Maps Premier (płatną), która daje 100 000 żądań geokodowania dziennie za około 10 000 rocznie (to dużo - przy buforowaniu po stronie serwera powinieneś nie osiągać tego limitu, chyba że jesteś dużą witryną lub wykonujesz intensywne przetwarzanie danych). Bez buforowania po stronie serwera i korzystania z obecnego podejścia będziesz w stanie wykonać 800 odsłon dziennie!

Gdy zdasz sobie sprawę, że inni dostawcy naliczają opłaty za geokod , zrozumiesz, że powinieneś buforować wyniki w bazie danych. Przy takim podejściu kosztowałby około 10 centów amerykańskich za wyświetlenie strony!

Twoje pytanie brzmi: czy możesz obejść limit przepustnicy, który daje ci Google? Pewnie. Wystarczy złożyć wniosek z różnych adresów IP. Heck, możesz proxy połączeń za pośrednictwem elastycznego IPA Amazon i zawsze będziesz mieć nowe świeże 2500 przydzielonych połączeń. Ale oczywiście, oprócz tego, że jest nielegalny (skutecznie obchodzisz ograniczenia nałożone przez warunki korzystania z Google Maps), robisz włamanie, aby wyeliminować nieodłączną wadę projektową, którą masz w swoim systemie.

Więc jaki jest właściwy sposób dla tego przypadku użycia? Zanim zadzwonisz do Google Geocode API, wyślij go na swój serwer i zapytaj, czy znajduje się w pamięci podręcznej. Jeśli nie jest, należy wywołać geokod, zapisać go w pamięci podręcznej i zwrócić wynik.

Istnieją inne podejścia, ale to powinno zacząć od właściwego kierunku.

Aktualizacja: z poniższych komentarzy wynika, że ​​używasz PHP, więc oto przykład kodu, jak to zrobić poprawnie (zalecenie samego zespołu Google) https://developers.google.com/maps/articles/phpsqlsearch_v3

Ragi Yaser Burhum
źródło
Czy masz przykład, który mógłbym śledzić wysyłając go na serwer itp.?
Rob
Jaki jest twój backend CMS? (Zakładam, że możesz / wiesz, jak to zmienić i po prostu chcę prostego przykładu, który pokazuje, jak to zrobić w wybranym języku. Nie potrzebujesz przykładu js po stronie klienta, czy tak? Czy używasz js ramy takie jak jquery?
Ragi Yaser Burhum
Będziesz także musiał podać więcej informacji o tym, jak dane znacznika dostają się do twojego systemu
Ragi Yaser Burhum
1
DOBRZE. Php więc. Ten fragment z Dokumentacji Google powinien zawierać część mysql i php code.google.com/apis/maps/articles/phpsqlgeocode.html
Ragi Yaser Burhum
1
Zobacz 10.1.3 (b), aby dowiedzieć się, jakie rodzaje buforowania są dozwolone. developers.google.com/maps/terms#section_10_12
Paul Ramsey
14

Myślę, że Sasa ma rację pod każdym względem.

Jeśli chodzi o wysyłanie wszystkich adresów jednocześnie, jedną z opcji jest wysyłanie żądań w odstępach czasu. W przeszłości, gdy korzystałem z JavaScript, wybrałem opóźnianie żądań o 0,25 (wydaje się, że działa!) Sekund przy użyciu

setTimeout( [FUNCTION CALL] , 250 )

metoda.

W .NET wybrałem:

System.Threading.Thread.Sleep(250);

Wydaje się działać.

EDYCJA: Nie mogę tego naprawdę przetestować, ale to powinno / może działać!

Przykład Javascript. AddressArray przechowuje ciągi, które są adresami ...

for (var i = 0; i < addressArray.length; i++0 
{

setTimeout('googleGeocodingFunction(' + addressArray[i] + ')' , 250);

}

EDYTOWAĆ:

for (var i = 0; i < address.length; i++) {
    function(i) {
        setTimeout(geocoder.geocode({ 'address': address[i] }, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                places[i] = results[0].geometry.location;

                var marker = new google.maps.Marker({ position: places[i], map: map });
                markers.push(marker);
                mc.addMarker(marker);
                google.maps.event.addListener(marker, 'click', function() {
                    if (!infowindow) {
                        infowindow = new google.maps.InfoWindow();
                    }

                    // Setting the content of the InfoWindow
                    infowindow.setContent(popup_content[i]);

                    // Tying the InfoWindow to the marker 
                    infowindow.open(map, marker);
                });

                // Extending the bounds object with all coordinates 
                bounds.extend(places[i]);

                // Adjusting the map to new bounding box 
                map.fitBounds(bounds)
            } else {
                alert("Geocode was not successful for the following reason: " + status);
            }
        }), 250);// End of setTimeOut Function - 250 being a quarter of a second. 
    } 
}
CatchingMonkey
źródło
Dziękuję za odpowiedź. Jak mogę to wprowadzić do mojego kodu? To wszystko jest trochę nowe, więc potrzebujesz trzymania ręki. Powinieneś być w stanie zobaczyć mój kod źródłowy.
Rob
Który kawałek? Jakiego języka używasz?
CatchingMonkey
Używam javascript, jak ustawić interwał?
Rob
Edytowałem moją odpowiedź.
CatchingMonkey
Zrealizowane także miałem na myśli setTimeout () ... Dzięki Casey.
CatchingMonkey
9

Wygląda na to, że osiągasz limit równoczesnych żądań nałożony przez Google (chociaż nie mogę znaleźć odniesienia do tego, jaki jest limit). Będziesz musiał rozdzielić swoje żądania, aby nie wysłać jednocześnie 125 wniosków. Pamiętaj, że istnieje również limit 2500 żądań geokodów dziennie.

Aby uzyskać więcej informacji, zapoznaj się z dokumentem Google Geocoding Strategies .

Aktualizacja: Jako dodatkowe rozwiązanie zainspirowane postem Mapperza, możesz pomyśleć o utworzeniu nowej tabeli Google Fusion , przechowywaniu adresu i wszelkich powiązanych danych w tabeli oraz geokodowaniu tabeli za pomocą interfejsu internetowego. Istnieje ograniczenie liczby żądań geokodów, które będzie generować Tabela Fusion, jednak limit jest dość duży. Po osiągnięciu limitu konieczne będzie ponowne przesłanie żądania geokodu, a tabele syntezy zaczną od miejsca, w którym zostało przerwane. Dodatkową zaletą tego podejścia jest ogromna poprawa prędkości, ponieważ wystarczy geokodować RAZ, a przy obecnym rozwiązaniu trzeba geokodować przy każdym obciążeniu, szybko osiągając dzienne limity.

Sasa Ivetic
źródło
Wydawało mi się, że przekroczę limit, jestem tak nowy, że myślę, że potrzebuję przykładu kodu, aby pomóc.
Rob
Przeglądałem tabele Google Fusion i natknąłem się na kilka problemów. 1. Musisz ręcznie geokodować adresy (poprzez plik-> geokod) w tabeli, czy można to zrobić automatycznie? 2. Niektóre znaczniki pojawiają się tylko przy określonych poziomach powiększenia, podczas gdy inne pokazują niezależnie od poziomu powiększenia. Oto przykład - mediwales.com/mapping/example. Ostatecznie chcę wyeksportować moje dane Wordpress (tj. Wszystkie adresy firmowe) do tabeli syntezy, geokodować je automatycznie, a następnie pobrać wszystkie te geokodowane adresy i natychmiast wydrukować mapę.
Rob
7

Oto jak dławię moje żądania geokodu w javascript, adresy są tablicą zawierającą każdy adres do geokodu:

for (i=0;i<=addresses.length;i++) {
    setTimeout( function () {
            geocoder.geocode( { 'address': addresses[i]}, function(results, status) {

                if (status == google.maps.GeocoderStatus.OK) { 

                    //create and add marker to map based off geocode result
                    var marker = new google.maps.Marker({  
                        map: map,
                        title: results[0].formatted_address,
                        position: results[0].geometry.location
                    });

                 } //EDIT, was missing the closing bracket here
            });

    }, i * 1500);
}

Zasadniczo dodaje to drugą i połowę między każdym żądaniem geokodowania.

Casey
źródło
Dziękuję za odpowiedź. Dostaję pustą stronę, gdy próbuję zintegrować z moim kodem - mediwales / mapping
Rob
Czy używasz narzędzi do debugowania, które mogłyby wskazać błąd? Jeśli nie, spróbuj użyć firebuga wtyczki FireFox. Może być bardzo przydatny w takich sytuacjach.
Casey
Nie jestem nie. Nie jestem pewien, czy umieściłem kod we właściwym miejscu, zaktualizuję moje pytanie przy mojej próbie.
Rob
W moim przykładzie kodu brakowało nawiasu zamykającego. Zredagowałem swoją odpowiedź i dodałem ją z komentarzem. Wygląda jednak na to, że nie był to problem w przykładowym kodzie. Czy otrzymujesz pustą stronę lub pustą mapę? Pusta strona oznacza, że ​​w kodzie javascript występuje błąd składniowy. Pusta mapa (bez znaczników) oznaczałaby problem z kodem geokodującym.
Casey
1
Cześć. Miałem jeszcze jedną odpowiedź na twoją odpowiedź. Opóźnienie działa teraz, ale nie można nakreślić markerów. Z mojego kodu są to ważne bity, które wykreślają znaczniki - (funkcja (i) {i}) (i); bez nich nie spiskuje, nawet bez dodania opóźnienia.
Rob
5

Próbowałem już teraz strony i wydaje się, że teraz działa .

Chociaż uważam, że podejście z timerem, którego obecnie używasz, jest prawidłowe i o ile wiem, jedyne, które będzie działać bez wymagającego wsparcia po stronie serwera, powinienem zasugerować następujące zmiany (mogłem przepisać twoje funkcje geokodowania) skorzystać z localStorage .

Lokalny magazyn to stosunkowo nowa technologia wbudowana w większość przeglądarek, która pozwala stronie internetowej przechowywać dane na kliencie. Jest nieco podobny do plików cookie, ale ma znacznie większą moc i nie zawsze jest ponownie wysyłany do serwera (w przeciwieństwie do plików cookie).

Moim celem jest zapisanie adresu geokodowanego na kliencie, aby w przypadku odświeżenia strony przez użytkownika nie było potrzeby ponownego wywoływania na nim funkcji geokodera Google. Poniższa implementacja jest prymitywna (powinniśmy dodać kod, aby sprawdzić nieaktualne rekordy i prawdopodobnie potrzebujemy lepszego klucza buforowania niż indeks), ale powinno wystarczyć, aby zacząć. Mam nadzieję, że to pomoże.

(function() { 

window.onload = function() { 
 var mc;
// Creating an object literal containing the properties we want to pass to the map 
var options = { 
zoom: 0, maxZoom: 0, 
center: new google.maps.LatLng(52.40, -3.61), 
mapTypeId: google.maps.MapTypeId.ROADMAP 
}; 

// Creating the map 
var map = new google.maps.Map(document.getElementById('map'), options); 

// Creating a LatLngBounds object 
var bounds = new google.maps.LatLngBounds(); 

// Creating an array that will contain the addresses 
var places = []; 

// Creating a variable that will hold the InfoWindow object 
var infowindow; 
mc = new MarkerClusterer(map);
var popup_content = [..redacted..];

var geocoder = new google.maps.Geocoder(); 

var markers = [];

// Adding a LatLng object for each city 
function geocodeAddress(i) {
     // check if localStorage is available (it is now available on most modern browsers)
     // http://html5tutorial.net/tutorials/working-with-html5-localstorage.html
     // NB: this *must* be improved to handle quota limits, age/freshness, etc
     if(localStorage && localStorage['address_'+i]) {
        places[i]=JSON.parse(localStorage['address_'+i]);
        addPlace(i);
     } else {
      geocoder.geocode( {'address': address[i]}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            places[i] = results[0].geometry.location;
            if(localStorage) {
               // cache result locally on the browser, this will help reducing the number of requests
               // to the google geocoder in case the user refreshes the page
               // remember: the more he will refresh, the more he's likely to hit the limit
               // (this is one case where refreshing or closing the browser does not work)
               localStorage['address_'+i]=JSON.stringify(results[0].geometry.location);
            }

            addPlace(i);
        } else { 
            console.log("Geocoding of address "+address[i]+" failed");
        }
    })
}

function addPlace(i) {
    // Adding the markers 
    var marker = new google.maps.Marker({position: places[i], map: map});
    markers.push(marker);
    mc.addMarker(marker);

    // Creating the event listener. It now has access to the values of i and marker as they were during its creation
    google.maps.event.addListener(marker, 'click', function() {
        // Check to see if we already have an InfoWindow
        if (!infowindow) {
            infowindow = new google.maps.InfoWindow();
        }

        // Setting the content of the InfoWindow
        infowindow.setContent(popup_content[i]);

        // Tying the InfoWindow to the marker 
        infowindow.open(map, marker);
    });

    // Extending the bounds object with each LatLng 
    bounds.extend(places[i]); 

    // Adjusting the map to new bounding box 
    map.fitBounds(bounds);
}

function geocode() {
    if (geoIndex < address.length) {
        geocodeAddress(geoIndex);
        ++geoIndex;
    }
    else {
        clearInterval(geoTimer);
    }
}
var geoIndex = 0;
var geoTimer = setInterval(geocode, 600);  // 200 milliseconds (to try out)

var markerCluster = new MarkerClusterer(map, markers); 
} 
})
(); 
unicoletti
źródło
Dziękuję bardzo, po prostu dając coś jeszcze, ale spróbuję tego za chwilę. Brzmi jak dobry pomysł.
Rob
Właśnie wypróbowałem (teraz powróciłem do poprzedniego), zadziałało za pierwszym razem, kiedy odświeżyłem, po prostu pokazałem pustą stronę.
Rob
spróbuj teraz, wystąpił błąd, pamiętaj również, że zmienna popup_content została zredagowana dla zwięzłości.
unicoletti
3

za pomocą geokoderów geopoli jestem w stanie geokodować dużą liczbę adresów bez żadnych problemów (nie jestem pewien konfiguracji plakatów lub czy może on uwzględnić zależność Pythona od swojego projektu)

oto mój test:

from geopy import geocoders

g = geocoders.GoogleV3()  #https://geopy.readthedocs.io/en/latest/#geopy.geocoders.GoogleV3

for x in xrange(1,10000):
    print x
    a = g.geocode("AV JOAO NAVES DE AVILA " + str(x) + " UBERLANDIA MG BRASIL")
    print a

fragment wyniku

7595 (u'Av. Jo \ xe3o Naves de \ xc1vila, 7595 - Segismundo Pereira, Uberl \ xe2ndia - Minas Gerais, 38408-288, Brazylia ', (-18.9388154, -48.2220562))

7596 (u'Av. Jo \ xe3o Naves de \ xc1vila, 7596 - Segismundo Pereira, Uberl \ xe2ndia - Minas Gerais, 38408-680, Brazylia ', (-18.938814, -48.2217423))

7597 (u'Av. Jo \ xe3o Naves de \ xc1vila, 7597 - Segismundo Pereira, Uberl \ xe2ndia - Minas Gerais, 38408-288, Brazylia ', (-18.9388128, -48.2220381))

7598 (u'Av. Jo \ xe3o Naves de \ xc1vila, 7598 - Segismundo Pereira, Uberl \ xe2ndia - Minas Gerais, 38408-680, Brazylia ', (-18.9388114, -48.2217242))

7599 (u'Av. Jo \ xe3o Naves de \ xc1vila, 7599 - Segismundo Pereira, Uberl \ xe2ndia - Minas Gerais, 38408-288, Brazylia ', (-18.9388102, -48.2220201))

7600 (u'Av. Jo \ xe3o Naves de \ xc1vila, 7600 - Segismundo Pereira, Uberl \ xe2ndia - Minas Gerais, 38408-680, Brazylia ', (-18.9388088, -48.2217062))

To wciąż działa i mam 7000 wyników.

EDYCJA: Po chwili dotarłem do końca ulicy, a Google zaczął dawać mi te same punkty, ale wygląda na to, że wciąż wysyła prośby i udziela dokładnych odpowiedzi.

George Silva
źródło
Geopy nie jest magią, nadal obowiązują ograniczenia użytkowania.
alphabetasoup
1

Ta funkcja php (nie wiem w jakim języku pracujesz, ale na pewno możesz go rozdzielić) używa Google Geolocator API. Podany adres zwróci znormalizowany adres i dłuższy. HTH.

// GEOLOCATEBYADDRESS
// @arg (string)address
// @return (array) ((int)flag,(array)address,array(rawresponse))

function geolocatebyaddress($lookupaddress){

    $lookupaddress=trim("$lookupaddress New Zealand");
    $lookupaddress=urlencode($lookupaddress);

    //send off google api lookup request
    $apiurl="http://maps.google.com/maps/api/geocode/json";
    $apiurl.="?address=$lookupaddress";
    $apiurl.="&region=NZ";
    $apiurl.="&sensor=false";

    if (function_exists("curl_init")) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $apiurl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $json = curl_exec($ch);
        curl_close($ch);
    }
    else     $json= file_get_contents($apiurl);

    //process response
    $response= json_decode($json,true);
    $approxflag=0;
    if ($response['status']=='OK' and count($response['results'])) {

        $aa= array();
        foreach($response['results'] as $cc=>$result) {
            //set keys
            foreach(array('street_number','road','suburb','city','postcode','region','lat','long') as $t){
                $aa[$cc][$t]='';
            }
            if ($result['geometry']){
                $aa[$cc]['lat']= $result['geometry']['location']['lat'];
                $aa[$cc]['long']=$result['geometry']['location']['lng'];
         }

            if (count($result['address_components'])){
                foreach ($result['address_components'] as $acs){
                    if ($acs['types'][0]=='street_number')               $aa[$cc]['street_number']= $acs['long_name']; 
                    if ($acs['types'][0]=='route')                       $aa[$cc]['road']=      $acs['long_name']; 
                    if ($acs['types'][0]=='sublocality')                 $aa[$cc]['suburb']=   $acs['long_name']; 
                    if ($acs['types'][0]=='locality')                    $aa[$cc]['city']=    $acs['long_name']; 
                    if ($acs['types'][0]=='postal_code')                 $aa[$cc]['postcode']= $acs['long_name']; 
                    if ($acs['types'][0]=='administrative_area_level_1') $aa[$cc]['region']=   $acs['long_name']; 
                }    
            }
            //successful?
            if ($result['geometry']['location_type']=='APPROXIMATE') $approxflag++;
            if (isset($result['partial_match']))  $approxflag++;
            if (!$aa[$cc]['street_number'])         $approxflag++;
        }
        if ($approxflag) return (array(1,$aa,$response));
        else return (array(2,$aa,$response));
    }
    else return (array(0,array(),$response));
}    
Piotr
źródło
Dzięki za odpowiedź, jak mam to włączyć do mojego kodu?
Rob
Przepraszam, przypuszczałem, że kodujesz witrynę. Ta funkcja jest używana jako część skryptu po stronie serwera, który na przykład pobiera adres wejściowy użytkownika, używa interfejsu Google Geocoder API, aby uzyskać współrzędne. Następnie możesz umieścić te współrzędne w swojej bazie danych, a kiedy musisz stworzyć mapę, po prostu przeszukaj zapytania i opracuj mapę ze znacznikami. W ten sposób nie będziesz nadużywał geokodera przy każdej renderowaniu strony jako podzielonej. (czy zanotowałeś mój komentarz? Próbuję ci pomóc, a karanie mnie wcale nie zachęci mnie wcale). Również nie muszę wspominać, że interfejs API wymaga użycia go z programem gmap.
Peter,
1

Właśnie zobaczyłem twoje zapytanie. Możesz wypróbować następujący kod. W części sprawdzania statusu geokodu w innym przypadku, wywołuj rekurencyjnie tę samą funkcję z odstępem czasu dla utraconych adresów.

function spotPosition(address) {
        geocoder.geocode({ 'address': address }, function (results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                var lat = results[0].geometry.location.lat();
                var lang = results[0].geometry.location.lng();
                setMarker(lat, lang);
            }
            else if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                setTimeout(function () {
                    //Recursively calling spotPosition method for lost addresses
                    spotPosition(address);
                }, 1000);
            }
        });
    }
jagath
źródło
0

Oto moje rozwiązanie:

zależności: Gmaps.js, jQuery

var Maps = function($) {
   var lost_addresses = [],
       geocode_count  = 0;

   var addMarker = function() { console.log('Marker Added!') };

   return {
     getGecodeFor: function(addresses) {
        var latlng;
        lost_addresses = [];
        for(i=0;i<addresses.length;i++) {
          GMaps.geocode({
            address: addresses[i],
            callback: function(response, status) {
              if(status == google.maps.GeocoderStatus.OK) {
                addMarker();
              } else if(status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                lost_addresses.push(addresses[i]);
              }

               geocode_count++;
               // notify listeners when the geocode is done
               if(geocode_count == addresses.length) {
                 $.event.trigger({ type: 'done:geocoder' });
               }
            }
          });
        }
     },
     processLostAddresses: function() {
       if(lost_addresses.length > 0) {
         this.getGeocodeFor(lost_addresses);
       }
     }
   };
}(jQuery);

Maps.getGeocodeFor(address);

// listen to done:geocode event and process the lost addresses after 1.5s
$(document).on('done:geocode', function() {
  setTimeout(function() {
    Maps.processLostAddresses();
  }, 1500);
});
Julio Betta
źródło
0

Nie możesz ominąć limitu geokodów mapy Google: musisz uzyskać i przechowywać informacje LatLng .

Jeśli masz kilka miast i nie chcesz ręcznie uzyskać LatLng, możesz użyć limitu czasu, aby stopniowo wywołać geocoder.geocode i zapisać informacje w obiekcie javascript, a następnie użyć, console.log(JSON.stringify(object, null, 4));aby uzyskać w konsoli ładny obiekt drukowany, więc dla przykład

            var locationsPosition = {
                    "Johannesburg - ZA": {
                        "lat": -26.2041028,
                        "lng": 28.047305100000017
                    },
                    "Chennai - IN": {
                        "lat": 13.0826802,
                        "lng": 80.27071840000008
                    }
             }

więc teraz możesz dodać znacznik za pomocą locationsPosition["Johannesburg - ZA"].lati.lng

Andrea Bisello
źródło
-1

Wygląda na to, że musisz zrobić jedną z dwóch rzeczy:

  1. zmień swój proces na buforowanie wyników, jeśli nie otrzymujesz tylu unikalnych na dzień; lub
  2. uaktualnij do usługi, która pozwala przetwarzać więcej dziennie

Jak ludzie wspominali wiele razy, ale nie mam osobistego doświadczenia, wydaje się, że licencja Google na 100 tys. Dziennie to około 10 tys. USD rocznie.

Jeśli chcesz mieć ten sam poziom dokładności lub lepszy (i nie musisz płacić tej ceny), możesz wypróbować naszą usługę. Za dużo mniej niż Google (prawie dziesiąty koszt) możesz uzyskać limit znacznie wyższy niż 2500 (nasz najniższy limit to 25 tys. Dziennie).

Oczywiście korzystając z naszego API płatnego geokodowania nie jest rozwiązaniem, które 100% uczciwości, nawet jeśli przyznanie się do tego nie jest rozsądne z biznesowego punktu widzenia. Zamiast tego sugeruję skorzystanie z opcji 1, zoptymalizowanie usługi do buforowania. Chyba że potrzebujesz więcej niż 2500 UNIKALNYCH geokodów na dzień.

Oświadczenie : Pracuję dla Geocode Farm (usługa, którą polecam).

Geocode.Farm Staff
źródło
Dlaczego zostało to odrzucone? Nie widzę, gdzie coś tu jest niedokładne lub nieprawidłowe?
Geocode.Farm Staff