3
votes

Question 1:

I am using Google Datastore (Java Client Libraries) with App Engine Flex and I am storing location data. I would like to query for a list of locations within a rectangular region.

My location entity looks like this:

Location
  - lat (eg. -56.1)
  - long (eg. 45.6)

Google Datastore has limitations for querying with multiple inequalities on different properties so I can't query using GQL like this:

SELECT * FROM Location WHERE lat <= @maxLat AND lat >= @minLat AND long <= @maxLong AND long >= @minLong

Where maxLat, minLat, maxLong, and minLong represent the bounding rectangle to search for Locations.

Currently I am querying using just one filter:

SELECT * FROM Location WHERE lat <= @maxLat AND lat >= @minLat

And from the returned results, I filter out the ones within the longitude bounds as well. Is there a better way to do this without resorting to this strategy ?

Question 2:

If I store the latitude/longitude combination as a Geopoint in Google Datastore, how can I check the latitude and longitude ?

For example if the location is stored like this:

Location
  - location (Geopoint)

I cannot filter on the lat/long within the Geopoint using the Java Client Libraries.

SELECT * FROM Location WHERE location.long <= @maxLong

Is there a workaround for the Datastore Geopoint property ?

2

2 Answers

2
votes

For an example of how to do this, look at the 'geomodel' library in Python.

Basic premise:

Divide your latitude and longitude values into discrete values (for example, 1 degree blocks), there by defining 'cells' that the value is contained in. Combine/hash then together so you have a single value.

Now, you can convert your queries for locations in a bounded rectangle by doing equality filters against these cells. Post filter at the end if your bounded rectangle doesn't entirely line up with the cell edges.

A related example for doing this with time is: Is datastore good for storing hr shifts?

-1
votes

Check out Datastore's REST API. There is an explicit value type for geopoints which you can find documented at the link below:

https://cloud.google.com/datastore/docs/reference/rest/v1/projects/runQuery#Value

All you'll need to do then is create a geopoint value property (let's call it geo) on an entity and then you'll be able to write GQL queries like this:

SELECT * FROM Address WHERE geo.latitude <= @maxLat AND geo.latitude >= @minLat