docs: function(key, options, callback){
      var self = this;
      //var layer = 0;
      var error = false,
        totalLayers,
        queryOpts = {}, 
        allLayers = [];
  
      // closure to check each layer and send back when done
      var collect = function(err, data){
        if (err) error = err;
        allLayers.push(data);
        if (allLayers.length == totalLayers){
          callback(error, allLayers);
        }
      };
          
      this._query('select info from "'+this.infoTable+'" where id=\''+(key+':'+(options.layer || 0 )+":info")+'\'', function(err, result){
        if ( err || !result || !result.rows || !result.rows.length ){
          callback('Not Found', []);
        } else if (result.rows[0].info.status == 'processing' && !options.bypassProcessing ) {
          callback( null, [{ status: 'processing' }]);
        } else {
            var info = result.rows[0].info;
            var select;
            if (options.simplify){
              select = 'select id, feature->>\'properties\' as props, st_asgeojson(st_simplifypreservetopology(geom::geometry, '+options.simplify+')) as geom from "' + key+':'+(options.layer || 0)+'"'; 
            } else {
              select = 'select id, feature->>\'properties\' as props, feature->>\'geometry\' as geom from "' + key+':'+(options.layer || 0)+'"'; 
            }
    
            // parse the where clause 
            if ( options.where ) { 
              if ( options.where != '1=1'){
                var clause = self.createWhereFromSql(options.where);
                select += ' WHERE ' + clause;
              } else {
                select += ' WHERE ' + options.where;
              }
            }
  
            // parse the geometry param from GeoServices REST
            if ( options.geometry ){
              var geom = self.parseGeometry( options.geometry );
  
              if (geom.xmin && geom.ymin ){
                var box = geom;
                if (box.spatialReference.wkid != 4326){
                  var mins = merc.inverse( [box.xmin, box.ymin] ),
                    maxs = merc.inverse( [box.xmax, box.ymax] );
                  box.xmin = mins[0];
                  box.ymin = mins[1];
                  box.xmax = maxs[0];
                  box.ymax = maxs[1];
                }
  
                select += (options.where ) ? ' AND ' : ' WHERE ';
                var bbox = box.xmin+' '+box.ymin+','+box.xmax+' '+box.ymax;
                select += 'ST_GeomFromGeoJSON(feature->>\'geometry\') && ST_SetSRID(\'BOX3D('+bbox+')\'::box3d,4326)';
                //select += 'ST_Intersects(ST_GeomFromGeoJSON(feature->>\'geometry\'), ST_MakeEnvelope('+box.xmin+','+box.ymin+','+box.xmax+','+box.ymax+'))';
              }
            }
  
            self._query( select.replace(/ id, feature->>'properties' as props, feature->>'geometry' as geom /, ' count(*) as count '), function(err, result){
              if (!options.limit && !err && result.rows.length && result.rows[0].count > self.limit ){
                callback( null, [{
                  exceeds_limit: true,
                  type: 'FeatureCollection',
                  features: [{}],
                  name: info.name,
                  sha: info.sha,
                  info: info.info,
                  updated_at: info.updated_at
                }]);
  
              } else {
                // ensure id order 
                select += " ORDER BY id";
                if ( options.limit ) {
                  select += ' LIMIT ' + options.limit;
                }
                if ( options.offset ) {
                  select += ' OFFSET ' + options.offset;
                }
                self.log.debug('Selecting data', select);
                self._query( select, function (err, result) {
                  if ( result && result.rows && result.rows.length ) {
                    var features = [],
                      feature;
                    result.rows.forEach(function(row, i){
                      features.push({
                        "type": "Feature",
                        "id": row.id,
                        "geometry": JSON.parse(row.geom),
                        "properties": JSON.parse(row.props)
                      });
                    });
                    callback( null, [{
                      type: 'FeatureCollection', 
                      features: features, //_.pluck(result.rows, 'feature'),
                      name: info.name, 
                      sha: info.sha, 
                      info: info.info, 
                      updated_at: info.updated_at 
                    }]);
                  } else {
                    callback( 'Not Found', [{
                      type: 'FeatureCollection',
                      features: []
                    }]);
                  }
                });
              }
            });
          }
      });
    }