diff --git a/lib/torque/leaflet/torque.js b/lib/torque/leaflet/torque.js index d77cec8..9962b98 100644 --- a/lib/torque/leaflet/torque.js +++ b/lib/torque/leaflet/torque.js @@ -212,25 +212,24 @@ L.TorqueLayer = L.CanvasLayer.extend({ } }, - getHistogramForVisibleRegion:function(varName,callback){ - var center = this._map.getCenter() - var zoom = this._map.getZoom() - - var xtile = parseInt(Math.floor( (center.lng + 180) / 360 * (1<> 2 - var yy = ytile >> 2 - var z = zoom - 2 - - this.provider.getHistogramForTiles(varName,[{x:xx,y:yy,z:z}],callback) - }, - - getHistogramForVisibleRegionBetter:function(varName,callback){ + getHistogramForVisibleRegion: function(varName, callback){ var tiles= [] for(var key in this._tiles){ - tiles.push(this._tiles[key].coord) + if (this._tiles[key]) { + tiles.push(this._tiles[key].coord) + } } - this.provider.getHistogramForTiles(varName,tiles,callback) + var tilesFilter = this.provider._generateBoundsQuery(tiles); + + this.provider.tablesForFilter(tilesFilter, function(tables) { + // select the table with less than 100k records + var table = tables.filter(function(f) { + return f.nrows < 50000; + }) + table = table.length ? table[0].table_name: this.options.overview_tables[this.options.overview_tables.length - 1] + this.provider.getHistogramForTiles(varName, tiles, table, callback) + }.bind(this)); + }, getHistogram:function(variable,callback,noBins){ diff --git a/lib/torque/provider/filterableJson.js b/lib/torque/provider/filterableJson.js index 377d8f2..e6ca0dd 100644 --- a/lib/torque/provider/filterableJson.js +++ b/lib/torque/provider/filterableJson.js @@ -293,10 +293,14 @@ var Profiler = require('../profiler'); this.filters = filters }, - _generateFiltersSQL: function(escape_quotes) { + _generateFiltersSQL: function(escape_quotes, filter_columns) { + filter_columns = filter_columns || []; escape_quotes = escape_quotes === undefined ? true: false; var self = this; - return Object.keys(this._filters).map(function(filterName){ + return Object.keys(this._filters).map(function(filterName) { + if (_.contains(filter_columns, filterName)) { + return "" + } var filter = self._filters[filterName] if (filter) { if (filter.type == 'range') { @@ -608,41 +612,41 @@ var Profiler = require('../profiler'); this._setReady(true); }, - _generateBoundsQuery:function(tiles){ + _generateBoundsQuery: function(tiles){ return tiles.map( function(tile){ return "(quadkey between (xyz2range("+tile.x+","+tile.y+","+tile.z+")).min and (xyz2range("+tile.x+","+tile.y+","+tile.z+")).max)" }).join(" or ") }, - getHistogramForTiles: function(varName,tiles,callback){ + getHistogramForTiles: function(varName, tiles, table, callback){ var sql = [ - 'with width as (', + 'with source as (', + 'select {varName} from {table} where ({bounds}) {filters}', + '),', + 'width as (', 'select min({varName}) as min,', 'max({varName}) as max,', '{bins} as buckets', - 'from {table}', + 'from source', '),', '_bw as ( select (max - min)/buckets as bw from width ),', 'histogram as (', 'select width_bucket({varName}, min, max, buckets) as bucket,', 'numrange(min({varName})::numeric, max({varName})::numeric, \'[]\') as range,', 'count(*) as freq', - 'from {table}, width ', - 'where {bounds}', - '{filters}', - //'where trip_time_in_secs between min and max', + 'from source, width ', 'group by bucket', 'order by bucket', ')', 'select bucket*bw as start, (bucket+1)*bw as end, bucket as bin, lower(range) as min, upper(range) as max, freq from histogram, _bw;' ] - var filters = this._generateFiltersSQL() ? " and "+ this._generateFiltersSQL() : "" + var filters = this._generateFiltersSQL(false, [varName]) ? " and "+ this._generateFiltersSQL(false, [varName]) : "" - var query = format(sql.join('\n'), this.options, { + var query = format(sql.join('\n'), { varName: varName, - table: this.options.table, + table: table, filters: filters, bounds: this._generateBoundsQuery(tiles), bins: 20 @@ -659,44 +663,21 @@ var Profiler = require('../profiler'); }); }, - getHistogram: function(varName, callback) { - - var sql = [ - 'with width as (', - 'select min({column}) as min,', - 'max({column}) as max,', - '20 as buckets', - 'from {table}', - '),', - '_bw as ( select (max - min)/buckets as bw from width ),', - 'histogram as (', - 'select width_bucket({column}, min, max, buckets) as bucket,', - 'numrange(min({column})::numeric, max({column})::numeric, \'[]\') as range,', - 'count(*) as freq', - 'from {table}, width ', - 'where {filters}', - //'where trip_time_in_secs between min and max', - 'group by bucket', - 'order by bucket', - ')', - 'select bucket*bw as start, (bucket+1)*bw as end, bucket as bin, lower(range) as min, upper(range) as max, freq from histogram, _bw;' - ] - - - var query = format(sql.join('\n'), this.options, { - column: varName, - table: this.options.table, - filters: this._generateFiltersSQL() + tablesForFilter: function(filter, callback) { + var filters = this._generateFiltersSQL() + if (filters) { + filters = "(" + filters + ") AND (" + filter + ")"; + } else { + filters = filter; + } + // calcualte the table to fecth the histogram + // use the tile 0,0,0 using the quadkey range query + var sql = format("SELECT * FROM selectivity(x:=0, y:=0, z:=0, tables:=ARRAY[{overview_tables}], where_clause:='{filters}') order by nrows desc", { + overview_tables: this.options.overview_tables.map(function(t) { return "'" + t + "'"; }).join(','), + filters: filters }); - - var self = this; - this.sql(query, function (data) { - if (data) { - var rows = JSON.parse(data.responseText).rows; - callback(rows); - } else { - callback(null); - } + this.sql(sql, function(data) { + callback(JSON.parse(data.responseText).rows); }); }