1

I'm using Fusion Tables layer on Google Maps. If I add a large where condition (where in 1000+ items), the layer does not load.

<!DOCTYPE html>
<html>
<head>
  <meta content="initial-scale=1.0, user-scalable=no" name="viewport">
  <meta charset="utf-8">
  <title>GEO View</title>
  <style>
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    #map {
      height: 100%;
      zoom: 0.7;
      -moz-transform: scale(0.8);
      -moz-transform-origin: 0 0;
    }
  </style>
</head>
<body>
  <div id="map"></div>
  <script>
    var arr = ['37159'];
    var draw_str = ['06037', '06043', '06057', '06065', '06079', '06097', '08011', '08037', '08051', '08069', '08099', '08119', '12041', '12075', '12113', '12123', '13015', '13029', '13095', '13151', '13161', '13169', '13197', '13209', '13213', '13235', '13263', '13267', '13273', '13275', '13293', '13305', '13319', '13990', '16017', '16023', '16047', '16049', '17015', '17043', '17053', '17077', '17079', '17081', '17129', '17141', '17197', '18019', '18043', '18067', '18105', '18115', '18119', '18127', '18147', '19013', '19031', '19067', '19079', '19087', '19111', '19113', '19127', '19153', '19161', '19169', '19175', '19187', '20009', '20019', '20037', '20039', '20051', '20059', '20067', '20087', '01017', '01035', '01053', '01073', '01081', '01127', '02282', '05007', '05031', '05039', '05053', '05067', '05087', '05089', '05119', '05123', '37025', '37037', '37057', '37077', '37123', '37153', '37157', '37159', '37193', '38017', '38045', '38051', '38065', '38101', '39007', '39019', '39021', '39049', '39057', '39059', '39063', '39069', '39081', '39089', '39091', '39097', '39101', '39139', '39153', '39167', '40003', '40019', '40087', '40129', '40153', '41011', '41027', '41049', '42013', '42021', '42035', '42037', '42041', '42055', '42063', '42073', '42077', '42085', '42091', '42109', '42115', '42131', '72027', '72051', '72055', '72057', '72065', '72073', '72087', '72129', '45033', '45035', '45059', '45071', '20095', '20099', '20101', '20107', '20109', '20117', '20133', '20139', '20177', '20195', '20209', '21029', '21031', '21037', '21059', '21061', '21083', '21113', '21127', '21157', '21173', '21211', '21217', '21229', '21239', '22013', '22035', '22049', '22055', '22065', '22079', '22103', '23005', '23025', '4001', '4003', '4005', '4007', '4009', '4011', '4012', '4013', '4015', '4017', '4019', '4021', '4023', '4025', '4027', '5001', '5003', '5005', '5007', '5009', '5011', '5013', '5015', '5017', '5019', '5021', '5023', '5025', '5027', '5029', '5031', '5033', '5035', '5037', '5039', '5041', '5043', '5045', '5047', '5049', '5051', '5053', '5055', '5057', '5059', '5061', '5063', '5065', '5067', '5069', '5071', '5073', '5075', '5077', '5079', '5081', '5083', '5085', '5087', '5089', '5091', '5093', '5095', '5097', '5099', '5101', '5103', '5105', '5107', '5109', '5111', '5113', '5115', '5117', '5119', '5121', '5123', '5125', '5127', '5129', '5131', '5133', '5135', '5137', '5139', '5141', '5143', '5145', '5147', '5149', '6001', '6003', '6005', '6007', '6009', '6011', '6013', '6015', '6017', '6019', '6021', '6023', '6025', '6027', '6029', '6031', '6033', '6035', '6037', '6039', '6041', '6043', '6045', '6047', '6049', '6051', '6053', '6055', '6057', '6059', '6061', '6063', '6065', '6067', '6069', '6071', '6073', '6075', '6077', '6079', '6081', '6083', '6085', '6087', '6089', '6091', '6093', '6095', '6097', '6099', '6101', '6103', '6105', '6107', '6109', '6111', '6113', '6115', '8001', '8003', '8005', '8007', '8009', '8011', '8013', '8014', '8015', '8017', '8019', '8021', '8023', '8025', '8027', '8029', '8031', '8033', '8035', '8037', '8041', '8039', '8043', '8045', '8047', '8049', '8051', '8053', '8055', '8057', '8059', '8061', '8063', '8065', '8067', '8069', '8071', '8073', '8075', '8077', '8079', '8081', '8083', '8085', '8087', '8089', '8091', '8093', '8095', '8097', '8099', '8101', '8103', '8105', '8107', '8109', '8111', '8113', '8115', '8117', '8119', '8121', '8123', '8125', '9001', '9003', '9005', '9007', '9009', '9011', '9013', '9015', '10001', '10003', '10005', '11001', '12001', '12003', '12005', '12007', '12009', '12011', '12013', '12015', '12017', '12019', '12021', '12023', '12027', '12029', '12031', '12033', '12035', '12037', '12039', '12041', '12043', '12045', '12047', '12049', '12051', '12053', '12055', '12057', '12059', '12061', '12063', '12065', '12067', '12069', '12071', '12073', '12075', '12077', '12079', '12081', '12083', '12085', '12086', '12087', '12089', '12091', '12093', '12095', '12097', '12099', '12101', '12103', '12105', '12107', '12109', '12111', '12113', '12115', '12117', '12119', '12121', '12123', '12125', '12127', '12129', '12131', '12133', '13001', '13003', '13005', '13007', '13009', '13011', '13013', '13015', '13017', '13019', '13021', '13023', '13025', '13027', '13029', '13031', '13033', '13035', '13037', '13039', '13043', '13045', '13047', '13049', '13051', '13053', '13055', '13057', '13059', '13061', '13063', '13065', '13067', '13069', '13071', '13073', '13075', '13077', '13079', '13081', '13083', '13085', '13089', '13087', '13091', '13093', '13095', '13097', '13099', '13101', '13103', '13105', '13107', '13109', '13111', '13113', '13115', '13117', '13119', '13121', '13123', '13125', '13127', '13129', '13131', '13133', '13135', '13137', '13139', '13141', '13143', '13145', '13147', '13149', '13151', '13153', '13155', '13157', '13159', '13161', '13163', '13165', '13167', '13169', '13171', '13173', '13175', '13177', '13179', '13181', '13183', '13185', '13187', '13189', '13191', '13193', '13195', '13197', '13199', '13201', '13205', '13207', '13209', '13211', '13213', '13215', '13217', '13219', '13221', '13223', '13225', '13227', '13229', '13231', '13233', '13235', '13237', '13239', '13241', '13243', '13245', '13247', '13249', '13251', '13253', '13255', '13257', '13259', '13261', '13263', '13265', '13267', '13269', '13271', '13273', '13275', '13277', '13279', '13281', '13283', '13285', '13287', '13289', '13291', '13293', '13295', '13297', '13299', '13301', '13303', '13305', '13307', '13309', '13311', '13313', '13315', '13317', '13319', '13321', '15001', '15003', '15005', '15007', '15009', '16001', '16003', '16005', '16007', '16009', '16011', '16013', '16015', '16017', '16019', '16021', '16023', '16025', '16027', '16029', '16031', '16033', '16035', '16037', '16039', '16041', '16043', '16045', '16047', '16049', '16051', '16053', '16055', '16057', '16059', '16061', '16063', '16065', '16067', '16069', '16071', '16073', '16075', '16077', '16079', '16081', '16083', '16085', '16087', '17001', '17003', '17005', '17007', '17009', '17011', '17013', '17015', '17017', '17019', '17021', '17023', '17025', '17027', '17029', '17031', '17033', '17035', '17037', '17039', '17041', '17043', '17045', '17047', '17049', '17051', '17053', '17055', '17057', '17059', '17061', '17063', '17065', '17067', '17069', '17071', '17073', '17075', '17077', '17079', '17081', '17083', '17085', '17087', '17089', '17091', '17093', '17095', '17097', '17099', '17101', '17103', '17105', '17107', '17109', '17111', '17113', '17115', '17117', '17119', '17121', '17123', '17125', '17127', '17129', '17131', '17133', '17135', '17137', '17139', '17141', '17143', '17145', '17147', '17149', '17151', '17153', '17155', '17157', '17159', '17161', '17163', '17165', '17167', '17169', '17171', '17173', '17175', '17177', '17179', '17181', '17183', '17185', '17187', '17189', '17191', '17193', '17195', '17197', '17199', '17201', '17203', '18001', '18003', '18005', '18007', '18009', '18011', '18013', '18015', '18017', '18019', '18021', '18023', '18025', '18027', '18029', '18031', '18033', '18035', '18037', '18039', '18041', '18043', '18045', '18047', '18049', '18051', '18053', '18055', '18057', '18059', '18061', '18063', '18065', '18067', '18069', '18071', '18073', '18075', '18077', '18079', '18081', '18083', '18085', '18087', '18089', '18091', '18093', '18095', '18097', '18099', '18101', '18103', '18105', '18107', '18109', '18111', '18113', '18115', '18117', '18119', '18121', '18123', '18125', '18127', '18129', '18131', '18133', '18135', '18137', '18139', '18141', '18143', '18145', '18147', '18149', '18151', '18153', '18155', '18157', '18159', '18161', '18163', '18165', '18167', '18169', '18171', '18173', '18175', '18177', '18179', '18181', '18183', '19001', '19003', '19005', '19007', '19009', '19011', '19013', '19015', '19017', '19019', '19021', '19023', '19025', '19027', '19029', '19031', '19033', '19035', '19037', '19039', '19041', '19043', '19045', '19047', '19049', '19051', '19053', '19055', '19057', '19059', '19061', '19063', '19065', '19067', '19069', '19071', '19073', '19075', '19077', '19079', '19081', '19083', '19085', '19087', '19089', '19091', '19093', '19095', '19097', '19099', '19101', '19103', '19105', '19107', '19109', '19111', '19113', '19115', '19117', '19119', '19121', '19123', '19125', '19127', '19129', '19131', '19133', '19135', '19137', '19139', '19141', '19143', '19145', '19147', '19149', '19151', '19153', '19155', '19157', '19159', '19161', '19163', '19165', '19167', '19169', '19171', '19173', '19175', '19177', '19179', '19181', '19183', '19185', '19187', '19189', '19191', '19193', '19195', '19197', '20001', '20003', '20005', '20007', '20009', '20011', '20013', '20015', '20017', '20019', '20021', '20023', '20025', '20027', '20029', '20031', '20033', '20035', '20037', '20039', '20041', '20043', '20045', '20047', '20049', '20051', '20053', '20055', '20057', '20059', '20061', '20063', '20065', '20067', '20069', '20071', '20073', '20075', '20077', '20079', '20081', '20083', '20085', '20087', '20089', '20091', '20093', '20095', '20097', '20099'];

    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 5,
        disableDefaultUI: true,
        center: {
          lat: 38.755724,
          lng: -96.492369
        }
      });
      mark();
      //Draw layer Function
      function mark() {
        layer = new google.maps.FusionTablesLayer({
          query: {
            select: 'geometry',
            from: '1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa'
          },
          styles: [{
            polygonOptions: {
              fillColor: '#000000',
              fillOpacity: 0.001
            }
          }, {
            where: "'GEO_ID2' IN (" + draw_str.toString() + ")",

            polygonOptions: {
              fillOpacity: 0.3
            }
          }]
        });

        layer.setMap(map);
      }
    }
  </script>
  <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBMtoh9P3UkoxbXndKu_HOP7KsVwTRvxGU&callback=initMap"></script>
</body>
</html>

I figured it is a GET request length issue. Is there a way to overcome this? Some way of using POST instead of GET, or other alternatives.

Please note the above where clause is just an example, it should work for more GEO_ID2.

approxiblue
  • 6,982
  • 16
  • 51
  • 59
dang
  • 2,342
  • 5
  • 44
  • 91

2 Answers2

2

If you use the Fusion Tables layer, your map tile requests will end up with long query strings exceeding the maximum URL length. There are no layer settings to use POST instead of GET requests, so we'll have to avoid the problem by filtering map results client-side.

Inspired by this answer, we can:

  1. Use the Fusion Tables API, request all map data at once. The results will be huge, but the GET request is small:

    https://www.googleapis.com/fusiontables/v2/query?sql=select GEO_ID2, geometry from 1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa&key=<YOUR_API_KEY>
    
  2. Wrangle data. The "geometry" column is in GeoJSON. There are a few issues with the returned format: the outermost wrapping object is inconsistent, and the coordinate lists of the polygons don't have the same start and end points.

  3. Draw the GeoJSON features on the map using the Data layer. Adding styles and interactivity for the features is well-documented.

For this demo, only a small set of IDs is used, and IDs are looked up using array's indexOf(). With more IDs, consider using a faster lookup table.

html,
body,
#map {
  height: 100%;
  margin: 0;
  padding: 0;
}
<div id="map"></div>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?v=3"></script>
<script>
  var ids = ['17015', '17043', '17053', '17077', '17079', '17081', '17129', '17141', '17197', '18019', '18043', '18067'];

  var map;

  function initialize() {
    var mapOptions = {
      zoom: 7,
      disableDefaultUI: true,
      center: {
        lat: 41.8781,
        lng: -87.6298
      }
    };

    map = new google.maps.Map(document.getElementById('map'), mapOptions);
    map.data.setStyle({
      strokeWeight: 0,
      fillOpacity: 0.3,
    });

    // Basic interactivity
    map.data.addListener('mouseover', function(event) {
      map.data.revertStyle();
      map.data.overrideStyle(event.feature, {
        fillColor: '#FF0000',
        fillOpacity: 0.5,
      });
    });

    map.data.addListener('mouseout', function(event) {
      map.data.revertStyle();
    });

    // Send Fusion Tables JSONP request
    var url = ['https://www.googleapis.com/fusiontables/v2/query'];
    url.push('?sql=' + encodeURIComponent('SELECT GEO_ID2, geometry FROM 1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa'));
    url.push('&callback=drawMap');
    url.push('&key=AIzaSyBMtoh9P3UkoxbXndKu_HOP7KsVwTRvxGU');
    var script = document.createElement('script');
    script.src = url.join('');
    document.getElementsByTagName('body')[0].appendChild(script);
  }

  function drawMap(data) {
    var rows = data['rows'];

    for (var i = 0, rc = rows.length; i < rc; i++) {
      if (ids.indexOf(rows[i][0]) !== -1) {
        var geojson = {
          type: 'Feature',
          properties: {
            name: rows[i][0], // GEO_ID2
          }
        }

        // Second column: geometry (GeoJSON)
        var geometries = rows[i][1]['geometries'];
        if (geometries) {
          geojson['geometry'] = rows[i][1];
          for (var g = 0, len = geometries.length; g < len; g++) {
            validateLinearRings(geometries[g]['coordinates']);
          }
        } else {
          geojson['geometry'] = rows[i][1]['geometry'];
          validateLinearRings(geojson['geometry']['coordinates']);
        }

        map.data.addGeoJson(geojson);
      }
    }
  }

  function validateLinearRings(coordinates) {
    var len = coordinates.length;
    for (var i = 0; i < len; i++) {
      // Add the first point as the last, closing the loop
      // http://geojson.org/geojson-spec.html#linestring
      coordinates[i].push(coordinates[i][0]);
    }
  }

  google.maps.event.addDomListener(window, 'load', initialize);
</script>
Community
  • 1
  • 1
approxiblue
  • 6,982
  • 16
  • 51
  • 59
  • would it get slow if I load all of it? When I run code snippet, it says - Google Maps API warning: NoApiKeys. – dang Jan 04 '17 at 07:15
  • It shows that warning but it will load nonetheless. You can add more IDs. I tried using your 1k data set. It takes time to load, but once loaded, you can interact with map normally, with little lag. – approxiblue Jan 04 '17 at 07:21
  • Also, I didn't understand when you said - consider using a faster lookup table. Is there a faster way of lookup? – dang Jan 04 '17 at 07:29
  • Like anything [here](http://stackoverflow.com/q/1208222/). It could be faster to look up an ID from a "map", instead of checking if it's in an array. That optimization is just extra though, once you get things working. – approxiblue Jan 04 '17 at 07:37
  • This is great. It's working quite well. The only problem is when I have an array of 3000 IDs, it takes around 3 minutes to load. Is there a way to optimize it? – dang Jan 04 '17 at 12:51
  • You can make the dataset smaller (containing only the IDs you want), so you don't have to filter on them; then you can switch back to using Fusion Tables layer. – approxiblue Jan 04 '17 at 15:42
  • I cannot make the dataset smaller, I need to plot 3000 and need it to be quick. Any ideas? – dang Jan 04 '17 at 16:03
1

The problem is the length of the request URL. Errors in the javascript console:

Failed to load resource: the server responded with a status of 400 ()
https://maps.googleapis.com/maps/vt?pb=!1m4!1m3!1i5!2i6!3i11!1m4!1m3!1i5!2i…Q!5i1!3m3!2sen-US!3sUS!5e18!4e3!12m1!5b1&callback=_xdc_._1mbvg&token=38465 

You need to reduce the length of the query string. One option (for this specific case, probably doesn't scale to all possible issues) is to remove the leading 0's in the query:

var draw_str = ['6037', '6043', '6057', '6065', '6079', '6097', '8011', '8037', '8051', '8069', '8099', '8119', '12041', '12075', '12113', '12123', '13015', '13029', '13095', '13151', '13161', '13169', '13197', '13209', '13213', '13235', '13263', '13267', '13273', '13275', '13293', '13305', '13319', '13990', '16017', '16023', '16047', '16049', '17015', '17043', '17053', '17077', '17079', '17081', '17129', '17141', '17197', '18019', '18043', '18067', '18105', '18115', '18119', '18127', '18147', '19013', '19031', '19067', '19079', '19087', '19111', '19113', '19127', '19153', '19161', '19169', '19175', '19187', '20009', '20019', '20037', '20039', '20051', '20059', '20067', '20087', '1017', '1035', '1053', '1073', '1081', '1127', '2282', '5007', '5031', '5039', '5053', '5067', '5087', '5089', '5119', '5123', '37025', '37037', '37057', '37077', '37123', '37153', '37157', '37159', '37193', '38017', '38045', '38051', '38065', '38101', '39007', '39019', '39021', '39049', '39057', '39059', '39063', '39069', '39081', '39089', '39091', '39097', '39101', '39139', '39153', '39167', '40003', '40019', '40087', '40129', '40153', '41011', '41027', '41049', '42013', '42021', '42035', '42037', '42041', '42055', '42063', '42073', '42077', '42085', '42091', '42109', '42115', '42131', '72027', '72051', '72055', '72057', '72065', '72073', '72087', '72129', '45033', '45035', '45059', '45071', '20095', '20099', '20101', '20107', '20109', '20117', '20133', '20139', '20177', '20195', '20209', '21029', '21031', '21037', '21059', '21061', '21083', '21113', '21127', '21157', '21173', '21211', '21217', '21229', '21239', '22013', '22035', '22049', '22055', '22065', '22079', '22103', '23005',  '23025'];

proof of concept fiddle

code snippet:

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
#map {
  height: 100%;
  zoom: 0.7;
  -moz-transform: scale(0.8);
  -moz-transform-origin: 0 0;
}
<div id="map"></div>
<script>
  var arr = ['37159'];
  var draw_str = ['6037', '6043', '6057', '6065', '6079', '6097', '8011', '8037', '8051', '8069', '8099', '8119', '12041', '12075', '12113', '12123', '13015', '13029', '13095', '13151', '13161', '13169', '13197', '13209', '13213', '13235', '13263', '13267', '13273', '13275', '13293', '13305', '13319', '13990', '16017', '16023', '16047', '16049', '17015', '17043', '17053', '17077', '17079', '17081', '17129', '17141', '17197', '18019', '18043', '18067', '18105', '18115', '18119', '18127', '18147', '19013', '19031', '19067', '19079', '19087', '19111', '19113', '19127', '19153', '19161', '19169', '19175', '19187', '20009', '20019', '20037', '20039', '20051', '20059', '20067', '20087', '1017', '1035', '1053', '1073', '1081', '1127', '2282', '5007', '5031', '5039', '5053', '5067', '5087', '5089', '5119', '5123', '37025', '37037', '37057', '37077', '37123', '37153', '37157', '37159', '37193', '38017', '38045', '38051', '38065', '38101', '39007', '39019', '39021', '39049', '39057', '39059', '39063', '39069', '39081', '39089', '39091', '39097', '39101', '39139', '39153', '39167', '40003', '40019', '40087', '40129', '40153', '41011', '41027', '41049', '42013', '42021', '42035', '42037', '42041', '42055', '42063', '42073', '42077', '42085', '42091', '42109', '42115', '42131', '72027', '72051', '72055', '72057', '72065', '72073', '72087', '72129', '45033', '45035', '45059', '45071', '20095', '20099', '20101', '20107', '20109', '20117', '20133', '20139', '20177', '20195', '20209', '21029', '21031', '21037', '21059', '21061', '21083', '21113', '21127', '21157', '21173', '21211', '21217', '21229', '21239', '22013', '22035', '22049', '22055', '22065', '22079', '22103', '23005', '23025'];

  function initMap() {
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 5,
      disableDefaultUI: true,
      center: {
        lat: 38.755724,
        lng: -96.492369
      }
    });
    mark();
    //Draw layer Function
    function mark() {
      layer = new google.maps.FusionTablesLayer({
        query: {
          select: 'geometry',
          from: '1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa'
        },
        styles: [{
          polygonOptions: {
            fillColor: '#000000',
            fillOpacity: 0.001
          }
        }, {
          //
          where: "'GEO_ID2' IN (" + draw_str.toString() + ")",

          polygonOptions: {
            fillOpacity: 0.3
          }
        }]
      });
      layer.setMap(map);
    }
  }
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • I will need to add more geo id's. The one was just sample. Is there other solution? – dang Oct 29 '16 at 09:45
  • You need to make the query string shorter than the maximum length. There are ways to do that, but each way will still eventually run into the limit. – geocodezip Oct 29 '16 at 14:51
  • Is there a way to do POST request so I don't run out of limit? I have 3251 geo ids. I may have to do 1000 or 2000 in the query. – dang Oct 29 '16 at 14:58
  • any thoughts on how can I do POST instead of GET? – dang Nov 03 '16 at 08:20