google fusion table select in from another table not working - google-maps

I am trying to select some rows based on row values from some other table but its not working. I have tried something like this
layer = new google.maps.FusionTablesLayer({
query: {
select: '\'Geocodable address\'',
from: '1m9CwnJrCfWNHCEQQkxqcQBzp-dA-S9KB8vLTpCrv',
where: 'ZCTA5CE10 in (select zip from 1V6aWLW-CEw2hRcPSzom1b9-Op6PS1ZQiyCH3GIRI)'
},
styles: [{
polygonOptions: _defaultStyle
}]
});
layer.setMap(map);
Its ignoring the where clause and drawing all rows on map. How to fix it?

Related

Sequelize geospatial query: find "n" closest points to a location

Using Sequelize and geospatial queries, if I want to find the "n" closest points to a certain location, how should the Sequelize query be?
Assume I have a model that looks something like this:
sequelize.define('Point', {geo: DataTypes.GEOMETRY('POINT')});
Now let's say we input 100 random points in the db through something like:
db.Point.create({geo: {type: 'Point', coordinates: [randomLng,randomLat]}});
Imagine we have a lat and lng variables to define a location, and we want to find the 10 closest points to it. when I run this query I get an error:
const location = sequelize.literal(`ST_GeomFromText('POINT(${lat} ${lng})', 4326)`);
db.Point.findAll({
attributes: [['distance', sequelize.fn('ST_Distance', sequelize.col('Point'), location)]],
order: 'distance',
limit: 10
});
// -> TypeError: s.replace is not a function
Any idea what is the issue / how to fix it?
Thx!
MySQL can give an error that function ST_Distance_Sphere does not exist. In that case you can use this alternative solution:
I hold point information separately as latitude and longitude decimals. Assume you should have a model that looks something like this:
sequelize.define('Point', {latitude: DataTypes.DECIMAL(11,2)},
{longitude: DataTypes.DECIMAL(11,2)});
Imagine we have a lat and lng variables to define a location, and we want to find the 10 closest points to it:
db.Point.findAll({
attributes: [[sequelize.fn('POW',sequelize.fn('ABS',sequelize.literal("latitude-"+lat)),2),'x1'],
[sequelize.fn('POW',sequelize.fn('ABS',sequelize.literal("longitude-"+lng)),2),'x2']],
order: sequelize.fn('SQRT', sequelize.literal('x1+x2')),
limit: 10
});
Update:
With Haversine Formula, distance is more accurate:
db.Point.findAll({
attributes: [[sequelize.literal("6371 * acos(cos(radians("+lat+")) * cos(radians(latitude)) * cos(radians("+lng+") - radians(longitude)) + sin(radians("+lat+")) * sin(radians(latitude)))"),'distance']],
order: sequelize.col('distance'),
limit: 10
});
When you surround sequelize.fn with brackets, you must also include a string as an alias:
[sequelize.fn('ST_Distance_Sphere', sequelize.literal('geolocation'), location), 'ALIASNAME']
Also, try changing ST_Distance to ST_Distance_Sphere. So:
const location = sequelize.literal(`ST_GeomFromText('POINT(${lng} ${lat})', 4326)`);
User.findAll({
attributes: [[sequelize.fn('ST_Distance_Sphere', sequelize.literal('geolocation'), location),'distance']],
order: 'distance',
limit: 10,
logging: console.log
})
.then(function(instance){
console.log(instance);
})
This is actually working for me.
obs: be sure you substitute 'User' with the model in which you have the geometry data type.
Update: If you still can't order using order: 'distance', maybe you should declare it in a var and use order: distance without quotes, like this:
var lat = parseFloat(json.lat);
var lng = parseFloat(json.lng);
var attributes = Object.keys(User.attributes);
var location = sequelize.literal(`ST_GeomFromText('POINT(${lng} ${lat})')`);
var distance = sequelize.fn('ST_Distance_Sphere', sequelize.literal('geolocation'), location);
attributes.push([distance,'distance']);
var query = {
attributes: attributes,
order: distance,
include: {model: Address, as: 'address'},
where: sequelize.where(distance, {$lte: maxDistance}),
logging: console.log
}
Update on distance accuracy:
The solution mentioned by sarikaya does seem to be more accurate. Here is how to do it using postgres:
var distance = sequelize.literal("6371 * acos(cos(radians("+lat+")) * cos(radians(ST_X(location))) * cos(radians("+lng+") - radians(ST_Y(location))) + sin(radians("+lat+")) * sin(radians(ST_X(location))))");
Building off #Edudjr's answer, this is what I did to get it to work in my project:
const location = sequelize.literal(`ST_GeomFromText('POINT(${ startLongitude } ${ startLatitude })')`)
const distance = sequelize.fn('ST_Distance_Sphere', sequelize.col('location'), location)
const inRadius = await Position.findAll({
order: distance,
where: sequelize.where(distance, { $lte: radius }),
logging: console.log
})
where Position is defined as:
sequelize.define('Position', {
location: DataTypes.GEOMETRY('POINT')
})
Note that Point requires the coordinates in the format of (longitude
latitude)
https://gis.stackexchange.com/questions/209008/incorrect-arguments-to-st-distance-sphere-in-special-cases
https://dba.stackexchange.com/questions/33410/whats-the-difference-between-pointx-y-and-geomfromtextpointx-y

More than one conditions in Where clause of Fusion Table Layer ignored in Styles

I am writing with reference to an earlier question of mine, which also had to do with the use of Where clauses for Fusion Table Layer in Google Maps. Link to earlier question. I have noticed that if the Where clause in Styles section has more than one filtering conditions in it, it is ignored altogether. Google Map/Fusion Tables Layers then ends up applying that Style to ALL of the features contained in that Fusion table. You can remove a filtering condition from the Where clause to make it a single filter where clause, and it then works as expected so I am pretty sure that it doesn't like multiple filtering condition in the SAME where clause (or the way I am writing it).
Here is an example that illustrates this behavior:
layer = new google.maps.FusionTablesLayer({
map: map,
options: {
templateId: 2
},
heatmap: { enabled: false },
query: {
select: "geometry",
from: "1D6d93-0iT2zUCw8IvkbpDPYDx2-jA0ZAWXi07mQD",
},
styles: [{
//note multiple filters in the same Where clause.
where: "((SHIFT_ID != 1) AND (SHIFT_ID != 2))",
//you'd expect the following Style option applied to only those map features
//which met above criteria. However, they are applied to ALL map features.
polylineOptions: {
strokeOpacity: 0.70,
strokeColor: "#FFFFFF",
strokeWeight: "5" }
//if Where clause is reduced to just having one filter, it works fine.
//For example, either of the following two work fine by themselves.
//where: "SHIFT_ID != 1" --OR--
//where: "SHIFT_ID != 2" etc.
}]
});
Geocodezip was right; query was invalid.
This is what I have been able to determine re use of queries for Fusion Tables.
Can have multiple fields/filters in one where clause.
Can't use brackets "()" for Boolean logic.
Instead of !=, use NOT EQUAL TO
For NULL values, check equality with '' (empty string).
Field names are case sensitive.
https://developers.google.com/fusiontables/docs/v2/sql-reference

Filtering a dropdown in Angular

I have a requirement for a select html element that can be duplicated multiple times on a page. The options for these select elements all come from a master list. All of the select elements can only show all of the items in the master list that have not been selected in any of the other select elements unless they just were duplicated.
When you select a new item from a duplicated select element, it seems to select the option after the one you selected even though the model still has the correct one set. This always seems to happen in IE11 and it happens sometimes in Chrome.
I realize this sounds convoluted, so I created a jFiddle example.
Try these steps:
Select Bender
Click the duplicate link
Select Fry (on the duplicated select)
Notice that the one that is selected is Leela but the model still has Fry (id:2) as the one selected
Can anyone tell me how I might get around this or what I might be doing wrong?
Here is the relevant Angular code:
myapp.controller('Ctrl', function ($scope) {
$scope.selectedIds = [{}];
$scope.allIds = [{ name: 'Bender', value: 1},
{name: 'Fry', value: 2},
{name: 'Leela', value: 3 }];
$scope.dupDropDown = function(currentDD) {
var newDD = angular.copy(currentDD);
$scope.selectedIds.push(newDD);
}
});
angular.module('appFilters',[]).filter('ddlFilter', function () {
return function (allIds, currentItem, selectedIds) {
//console.log(currentItem);
var listToReturn = allIds.filter(function (anIdFromMasterList) {
if (currentItem.id == anIdFromMasterList.value)
return true;
var areThereAny = selectedIds.some(function (aSelectedId) {
return aSelectedId.id == anIdFromMasterList.value;
});
return !areThereAny;
});
return listToReturn;
}
});
And here is the relevant HTML
<div ng-repeat="aSelection in selectedIds ">
Duplicate
<select ng-model="aSelection.id" ng-options="a.value as a.name for a in allIds | ddlFilter:aSelection:selectedIds">
<option value="">--Select--</option>
</select>
</div>
Hi I have just made a small change in your dupDropDown function as follows
$scope.dupDropDown = function(currentDD) {
$scope.selectedIds.push({});
}
Please check if this works for you.

Google map with two Fusion Table layers does not display second layer

I have a map that is displaying two fusion table layers. I have styled them both using the styleId attribute to take the styles defined in the Fusion Table UI instead of using the styles attribute when creating the layer in Google maps. From the maps docs, it mentions that you can have up to 5 fusion table layers, with one of them being styled.
Styles can only be applied to a single Fusion Tables layer per map. You may apply up to five styles to that layer.
What I'm not 100% clear on is if this applies to inline styles only, e.g.:
layer1 = new google.maps.FusionTablesLayer({
query: {
from: table1Id
},
styles: [
{markerOptions: {iconName: 'red_blank'}, where: 'age > 50'},
{markerOptions: {iconName: 'grn_blank'}, where: 'age <= 50'}
]
});
layer2 = new google.maps.FusionTablesLayer({
query: {
from: table2Id
},
styles: [ // This won't work because you can only style one table inline
{markerOptions: {iconName: 'red_blank'}, where: 'age > 50'},
{markerOptions: {iconName: 'grn_blank'}, where: 'age <= 50'}
]
});
or if it also applies to styles defined in the fusion table UI:
layer1 = new google.maps.FusionTablesLayer({
query: {
from: table1Id
},
options: {
styleId: 2, // Obtained from the fusion table UI
templateId: 1 // Obtained from the fusion table UI
}
})
layer2 = new google.maps.FusionTablesLayer({
query: {
from: table2Id
},
options: {
styleId: 2, // Obtained from the fusion table UI
templateId: 1 // Obtained from the fusion table UI
}
})
From my reading of the docs, it would seem that it's only the first type that is not allowed on multiple layers.
The styleId way of styling a table is actually not mentioned in the Google Maps docs, but this is the way the embed code generated in Fusion Tables when you "Publish" a map looks like, and it actually works for individual layers.
If I enable both layers (layer1.setMap(map)), only one of the layers gets displayed. If I disable a layer, the other one appears correctly.
Any help will be greatly appreciated.
It works with mixing inline-styles and styleId.
Demo with 5 layers, 4 layers use styleId and 1 layer uses 5 inline-styles , as you see the result is as expected 9 different styled markers: http://jsfiddle.net/doktormolle/Zk2CE/
The problem with your attempt: you are always using the same where-clause in the query(currently there is no where-clause, all rows will be selected).
When you define a where-clause in a style this will apply the style to the selected items, to all other items(that will not be matched by any where-clause in a style) the default-style will be applied(e.g. a red dot for a marker)
The result: when specific rows(items) will be selected by the query of more than 1 layer, only 1 style/styleId may be applied to these items(usually the style set with the last layer that has been added to the map).

Filtering fusion tables using where clause

I am trying to filter a fusion table using the WHERE clause in order to display land areas below a certain size. I am not sure if it is a simple problem with the syntax but this filter will not work for me. Here is the code:
var layer = new google.maps.FusionTablesLayer({
query: {
select: 'Geometry',
from: 4310315,
where: 'rollingarea' < 400,
}
});
I have tried different variations such as where 'rollingarea < 40' & "'rollingarea' < 400" but cant get it to work.
Any help would be much appreciated
Looking at your table, the column name is "ROLLING AREA".
Try:
"'ROLLING AREA' < 400"