SPARQL Query resource filter by another resource's data - filtering

studying for an exam I have in Advanced modelling and have a question in regards to a SPARQL approach to a problem. This is an exam question from last year's exam :
QUESTION : Write a SPARQL query that lists all nearby hotels in Paris with latitude and longitude that are within 0.006
degrees latitude and 0.01 degrees longitude of the hotel named “Hotel Saint-Germain-des-Pres”.
Assume you have an RDF graph that uses the dc:title predicate for all resource titles. Some of the
resources represent hotels. They have the rdf:type schema:Hotel .
The RDF graph also uses the schema:address predicate to describe the address of each hotel. An
address resource has rdf:type schema:PostalAddress . We will pretend each postal address has a
schema:city predicate that gives the hotel's city as a string literal.
Each hotel in the graph also has Geo coordinates for latitude and longitude.
So far I have come up with :
SELECT ?hotelName WHERE {
?hotel rdf:type schema:Hotel;
dc:title "Hotel Saint-Germain-des-Pres"^^xsd:string
geo:latitude ?targLat;
geo:longitude ?targLong .
?hotel rdf:type schema:Hotel;
schema:city "Paris"^^xsd:string;
dc:title ?hotelName;
geo:latitude ?lat
geo:longtitude ?long .
FILTER((geo:long <= targLong + 0.006 && geo:long >= targLong - 0.006) && (geo:lat <= targLat + 0.01 && geo:lat >= targLat - 0.01))
}
Pseudo: ?hotelName long & lat within long(0.006)/lat(0.01) of"Hotel Saint-Germain-des-Pres"
But hit a wall when it comes to relating that the latitude & longitude must be within another resource's location.
How is it possible to show this restriction in SPARQL?
Thanks for any answers in advance.

Related

I am trying to write an R script to calculate average ride length for each day based on user type using the aggregate function

I am trying to write an R script to calculate average ride length for each day and group by user type. The data structure has:
day_of_week (chr), Ride_length (num), user_type(chr)
The script is the following:
aggregate(divvy_2022$ride_length ~ divvy_2022$user_type ~ divvy_2022$day_of_week, FUN = mean)
I get this error:
Error in model.frame.default(formula = divvy_2022$ride_length ~ divvy_2022$user_type ~ :
object is not a matrix
What could be wrong?
I can't understand why the error comes up

Overpass API: query for counting amenity of specified type around set of lat lons

I'm trying to query data from the OSM Overpass API. Specifically I'm trying to determine the count of amenities of a given type around a point (using the 'around' syntax). When running this for many locations (lat, lons) I'm running into a TooManyRequests error.
I have tried to work around by setting sleep time pauses and playing with the timeout header and retry time, but I'm running into the same issue. I'm trying to find a way to adapt the query so that it just returns the count of amenities (of specified type) around each point, rather than the full json of nodes which is more data intensive. My current script is as follows;
# Running Overpass query for each point
results = {}
for n in range(0, 200):
name = df.loc[n]['city']
state = df.loc[n]['state_name']
rad = df.loc[n]['radius_m']
lat = df.loc[n]['lat']
lon = df.loc[n]['lng']
# Overpass query for amenities
start_time = time.time()
api = overpy.Overpass(max_retry_count=None, retry_timeout=2)
r = api.query(f"""
[out:json][timeout:180];
(node["amenity"="charging_station"](around:{rad}, {lat}, {lon});
);
out;
""")
print("query time for "+str(name)+", number "+str(n)+" = "+str(time.time() - start_time))
results[name] = len(r.nodes)
time.sleep(2)
Any help is much appreciated from other Overpass users!
Thanks
In general, you can run out count; to return a count from an overpass API query.
It's hard to say without knowing how your data is specifically structured, but you might have better luck using area to look at specific cities, or regions.
Here is an example that returns the count of all nodes tagged as charging station in Portland, Oregon:
/* charging stations in portland */
area[name="Oregon"]->.state;
area[name="Portland"]->.city;
(
node["amenity"="charging_station"](area.state)(area.city);
);
out count;

PostgreSQL DB location query with Fluent 4

I have an application that stores items with a latitude and longitude, I wanted to create a query that filters the items and paginates them by their distance to a given lat/lon pair.
I have read online and a lot of the solutions don't seem feasible within the constraints of fluent.
You'll want to use PostGIS for any kind of Geometric/Geographic query. Luckily there's a package for that! https://github.com/brokenhandsio/fluent-postgis
You can do filterGeograghyWithin() to find items within a certain distance. Note the geographic queries are better suited for these kind of transformations (and more accurate) as they take into account the curvature of the Earth.
The downside is you'll need to convert your lat/lon columns to a GeographicPoint2D which is the native PostGIS type, but given PostGIS is the de facto standard for this kind of work it's worth doing anyway
The best you could do is to calculate the angular distance (ang) from your given latitude (lat) and longitude (lng), and then select the square region that will include the circle. Then use Pythagoras to filter those lying within the required distance:
let ang2 = pow(ang, 2)
Point.query(on: req.db)
.filter(\.$lng >= lng - ang).filter(\.$lng <= lng + ang)
.filter(\.$lng >= lat - ang).filter(\.$lat <= lat + ang).all().flatMap { points in
let closePoints = points.filter { pow($0.lat - lat, 2) * pow($0.lng - lng, 2) <= ang2) }
// continue processing
}
}
EDIT: Following the OPs disclosure that he wants to paginate the results!
Capture the id values of the final set of Points and then filter on this. Something like:
let ang2 = pow(ang, 2)
Point.query(on: req.db)
.filter(\.$lng >= lng - ang).filter(\.$lng <= lng + ang)
.filter(\.$lng >= lat - ang).filter(\.$lat <= lat + ang).all().flatMap { points in
return points.filter { pow($0.lat - lat, 2) * pow($0.lng - lng, 2) <= ang2) }.map { $0.id }
}.flatMap { ids in
Point.query(on: req.db).filter(\.$id ~~ ids).paginate().flatMap { points in
// continue processing
}
}
}

Google Places Search AutoComplete filter results by Country in Swift 4

I am trying to filter the results from the API (Google Places) country wise.
I am aware I can do it, using code such as this:
let filter = GMSAutocompleteFilter()
filter.type = .establishment
filter.country = "SG"
SG is for Singapore but the thing is, where shall I place the code so that the results are filtered as per the country?

Postgresql earth_box algorithm

I found this tutorial how to find something in specified the radius. My question is what algorithm was used to implement it?
If you mean the earth_box, the idea is to come up with a data type that can be useful with a GIST index (inverted search tree):
http://www.postgresql.org/docs/current/static/gist-intro.html
See in particular the links at the bottom of the maintainers' page:
http://www.sai.msu.su/~megera/postgres/gist/
One leads to:
The GiST is a balanced tree structure like a B-tree, containing pairs. But keys in the GiST are not integers like the keys in a B-tree. Instead, a GiST key is a member of a user-defined class, and represents some property that is true of all data items reachable from the pointer associated with the key. For example, keys in a B+-tree-like GiST are ranges of numbers ("all data items below this pointer are between 4 and 6"); keys in an R-tree-like GiST are bounding boxes, ("all data items below this pointer are in Calfornia"); keys in an RD-tree-like GiST are sets ("all data items below this pointer are subsets of {1,6,7,9,11,12,13,72}"); etc. To make a GiST work, you just have to figure out what to represent in the keys, and then write 4 methods for the key class that help the tree do insertion, deletion, and search.
http://gist.cs.berkeley.edu/gist1.html
If you mean the earth distance itself, the meaty part of source is:
/* compute difference in longitudes - want < 180 degrees */
longdiff = fabs(long1 - long2);
if (longdiff > M_PI)
longdiff = TWO_PI - longdiff;
sino = sqrt(sin(fabs(lat1 - lat2) / 2.) * sin(fabs(lat1 - lat2) / 2.) +
                cos(lat1) * cos(lat2) * sin(longdiff / 2.) * sin(longdiff / 2.));
if (sino > 1.)
        sino = 1.;
return 2. * EARTH_RADIUS * asin(sino);
https://github.com/postgres/postgres/blob/master/contrib/earthdistance/earthdistance.c#L50
My math is too rusty to be affirmative on what the above does exactly, but my guess would be that it's computing the distance between two points on the surface of a sphere (without considering the height of the two points). In other words, nautical miles.