ฉันจะใส่รหัส Geocode 20 ที่อยู่โดยไม่ได้รับการตอบกลับ OVER_QUERY_LIMIT ได้อย่างไร


87

เมื่อใช้ Google Geocoder v3 หากฉันพยายามระบุตำแหน่งทางภูมิศาสตร์ 20 ที่อยู่ฉันจะได้รับ OVER_QUERY_LIMIT เว้นแต่ว่าฉันจะแบ่งเวลาให้ห่างกัน ~ 1 วินาที แต่จะใช้เวลา 20 วินาทีก่อนที่จะวางเครื่องหมายทั้งหมด

มีวิธีอื่นทำได้ไหมนอกจากเก็บพิกัดล่วงหน้า


ยังคงเป็นเช่นนี้อยู่หรือไม่? ข้อ จำกัด เดียวที่ฉันเห็นในเอกสารประกอบคือ: "ขีด จำกัด การสืบค้น 2,500 คำขอระบุตำแหน่งทางภูมิศาสตร์ต่อวัน" code.google.com/apis/maps/documentation/geocoding/…
russau

6
ไม่เกี่ยวกับจำนวนข้อความค้นหาทั้งหมดต่อผู้ใช้ต่อวัน แต่เกี่ยวกับจำนวนการสืบค้นในช่วงเวลาสั้น ๆ เช่นการสืบค้นแบบวนซ้ำ
Michiel van Oosterhout

เรามีใบอนุญาตประกอบธุรกิจที่ร้านของเราและเรายังคงพบปัญหานี้ว่าไม่สามารถจัดการคำขอมากกว่า 10 คำขอต่อวินาที ข้อแตกต่างเพียงอย่างเดียวระหว่างใบอนุญาตธุรกิจกับนักพัฒนาทั่วไปคือเรา จำกัด การโทรไว้ที่ 100,000 ครั้งต่อวัน
abhi

@michielvoo คุณแก้ปัญหานี้แล้วหรือยัง? ถ้าใช่โปรดช่วยฉันด้วย ฉันได้รับ OVER_QUERY_LIMIT คำถามของฉันใน SO Fiddle
Prabs

คำตอบ:


85

ไม่ไม่มีวิธีอื่นจริงๆ: หากคุณมีสถานที่หลายแห่งและต้องการแสดงสถานที่เหล่านั้นบนแผนที่ทางออกที่ดีที่สุดคือ:

  • ดึงข้อมูลละติจูด + ลองจิจูดโดยใช้ geocoder เมื่อสร้างสถานที่
  • จัดเก็บข้อมูลเหล่านั้นไว้ในฐานข้อมูลของคุณควบคู่ไปกับที่อยู่
  • และใช้ละติจูด + ลองจิจูดที่เก็บไว้เมื่อคุณต้องการแสดงแผนที่

แน่นอนว่านี่คือการพิจารณาว่าคุณมีการสร้าง / ปรับเปลี่ยนสถานที่น้อยกว่าที่คุณให้คำปรึกษาเกี่ยวกับสถานที่ตั้งมาก


ใช่หมายความว่าคุณจะต้องทำงานเพิ่มขึ้นอีกเล็กน้อยเมื่อบันทึกสถานที่ - แต่ยังหมายถึง:

  • คุณจะสามารถค้นหาตามพิกัดทางภูมิศาสตร์
    • เช่น " ฉันต้องการรายชื่อจุดที่อยู่ใกล้จุดที่ฉันตอนนี้ "
  • การแสดงแผนที่จะเร็วขึ้นมาก
    • แม้จะมีมากกว่า 20 แห่งก็ตาม
  • โอ้และเช่นกัน(สุดท้าย แต่ไม่ท้ายสุด) : จะได้ผล ;-)
    • คุณจะมีโอกาสน้อยที่จะถึงขีด จำกัด ของการเรียก X geocoder ใน N วินาที
    • และคุณจะมีโอกาสน้อยที่จะถึงขีด จำกัด ของการโทรหา geocoder Y ต่อวัน

ฉันอยากรู้ว่าคุณจะมั่นใจได้อย่างไรว่าผลลัพธ์นั้นถูกต้องหลังจากเวลาผ่านไปสักระยะหนึ่ง (สมมติว่าหนึ่งเดือน) คุณถามซ้ำทุกครั้งหรือไม่?
คริส

2
หากที่อยู่(ที่คุณมีอยู่แล้วในฐานข้อมูล - มิฉะนั้นคุณจะไม่สามารถระบุพิกัดทางภูมิศาสตร์ได้)ไม่เปลี่ยนแปลงโอกาสที่ละติจูด / ลองจิจูดควรเปลี่ยนไป และแน่นอนทุกครั้งที่มีการแก้ไขที่อยู่คุณควรค้นหา geocoder อีกครั้งเพื่อให้ได้ละติจูด + ลองจิจูดที่ตรงกับที่อยู่ใหม่
Pascal MARTIN

ฉันเก็บ lat / long ไว้ใน DB และดึงข้อมูลจาก DB ผ่าน AJAX เป็นอาร์เรย์ แต่จากนั้นควรส่งต่อไปยังลูปสคริปต์ java อีกครั้งมากกว่าที่ฉันได้รับ 173 ตำแหน่งจาก DB ตอนนี้แสดงสถานะ OVER_QUERY_LIMIT เดียวกัน กรุณาแนะนำ ...
Prabhu M

20

คุณไม่ต้องรอเต็มวินาทีสำหรับแต่ละคำขอ ฉันพบว่าหากฉันรอ 200 มิลลิวินาทีระหว่างแต่ละคำขอฉันสามารถหลีกเลี่ยงการตอบกลับ OVER_QUERY_LIMIT ได้และประสบการณ์ของผู้ใช้ก็ผ่านได้ ด้วยโซลูชันนี้คุณสามารถโหลด 20 รายการใน 4 วินาที

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

  setTimeout(function(){

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

  }, 200 * i);

}

5
แต่ (200 * i) หมายความว่าการหยุดชั่วคราวระหว่างแต่ละคำขอจะเพิ่มขึ้น ดังนั้นในการร้องขอครั้งที่ 3 คือ 600 แล้ว 800 เป็นต้น
โรมัน

เพียงแค่ลบ '* i'
คริส

9
setTimeout จะดำเนินการครั้งเดียว ดังนั้นถ้าฉันถูกต้อง (... , 200 * i) จะกำหนดเวลาการโทรแต่ละครั้งโดยคั่นด้วย 200ms (ตามที่ oyatek แสดงความคิดเห็น) ซึ่งเป็นสิ่งที่ gabeodess ต้องการบรรลุ กระแส (... , 200) จะดำเนินการทั้งหมดพร้อมกันหลังจากผ่านไป 200 มิลลิวินาที หรือฉันขาดอะไรไป?
lepe

@gabeodess - คุณควรทำsetIntervalตามจำนวนคำขอที่ต้องการแทนที่จะเป็นsetTimeoutและตั้งค่าเป็น100- ในกรณีที่จำนวนที่อยู่บางครั้งจะขยาย20จำนวนเงินในอนาคต
Rob Scott

4
@gabeodess ฉันได้ลองวิธีแก้ปัญหาของคุณแล้ว แต่ยังได้รับ OVER_QUERY_LIMIT Fiddle
Prabs

6

ขออภัยนี่เป็นข้อ จำกัด ของบริการ Google แผนที่

ขณะนี้ฉันกำลังทำงานกับแอปพลิเคชันโดยใช้คุณสมบัติการเข้ารหัสทางภูมิศาสตร์และฉันกำลังบันทึกที่อยู่ที่ไม่ซ้ำกันสำหรับผู้ใช้แต่ละราย ฉันสร้างข้อมูลที่อยู่ (เมืองถนนรัฐ ฯลฯ ) ตามข้อมูลที่ Google Maps ส่งคืนจากนั้นบันทึกข้อมูล lat / long ในฐานข้อมูลด้วย วิธีนี้จะป้องกันไม่ให้คุณต้องเขียนโค้ดใหม่และให้ที่อยู่ที่จัดรูปแบบไว้อย่างสวยงาม

อีกเหตุผลหนึ่งที่คุณต้องการทำเช่นนี้เนื่องจากมีการ จำกัด จำนวนที่อยู่รายวันที่สามารถระบุพิกัดทางภูมิศาสตร์จากที่อยู่ IP หนึ่ง ๆ ได้ คุณไม่ต้องการให้ใบสมัครของคุณล้มเหลวด้วยเหตุผลดังกล่าว


2

ฉันประสบปัญหาเดียวกันกับการพยายามใส่รหัสภูมิศาสตร์ 140 ที่อยู่

วิธีแก้ปัญหาของฉันคือการเพิ่มusleep (100000)สำหรับแต่ละลูปของคำขอ geocoding ถัดไป หากสถานะของคำขอคือ OVER_QUERY_LIMIT ระยะเวลาใช้งานจะเพิ่มขึ้น 50000 และมีการร้องขอซ้ำไปเรื่อย ๆ

และจากสาเหตุข้อมูลที่ได้รับทั้งหมด (lat / long) จะถูกเก็บไว้ในไฟล์ XML เพื่อไม่ให้เรียกใช้คำขอทุกครั้งที่โหลดเพจ


1
คำตอบของคุณคลุมเครือคุณกำลังอ้างถึงทางฝั่งเซิร์ฟเวอร์หรือเป็นจาวาสคริปต์นี้หากเป็นแบบหลัง usleep ไม่ใช่ฟังก์ชันดังนั้นจะไม่ถูกต้องหากเป็นแบบเดิมฉันขอแนะนำให้คุณแก้ไขคำตอบของคุณเพื่อระบุอย่างชัดเจน เป็นฝั่งเซิร์ฟเวอร์เพื่อหลีกเลี่ยงความไม่ชัดเจน
t0mm13b

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 Maps ดังนั้นความคิดเห็นอาจทำให้สับสน

การใช้งานค่อนข้างง่ายอย่างไรก็ตามวิธีการนั้นแตกต่างกันเล็กน้อย: แทนที่จะวนซ้ำและแก้ไขทีละที่อยู่คุณจะต้องส่งอาร์เรย์ของที่อยู่ไปยังคลาสและจะจัดการการค้นหาด้วยตัวเองโดยส่งคืนสัญญาที่ เมื่อแก้ไขแล้วจะส่งคืนอาร์เรย์ที่มีแอดเดรสที่แก้ไข (และไม่ได้รับการแก้ไข) ทั้งหมด

ตัวอย่าง:

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 และพบปัญหาเดียวกันกับคุณ ฉันสังเกตเห็นว่าฉันได้รับสถานะ OVER_QUERY_LIMIT หนึ่งครั้งทุกๆ 12 คำขอดังนั้นฉันจึงรอ 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.