MongoDB spatial query for Polygons - mongodb

I will build a GIS system based on polygons, not just points. I wanted to use MongoDB or PostGIS.
How do this in MongoDB?
Query A - get the center of a polygon
Query B - distance between two polygons
Query C - list of polygons that are part of a third that I specify
Query D - near-distance of the polygon
Support SRID?

MongoDB's geospatial indexing currently only indexes points. Although it does support proximity and bounds queries, documents are matched by a single point. You may be able to take advantage of multi-location documents and index multiple points along a polygon, which might support some of your queries with reduced precision; however, that would certainly not be ideal.
PostGIS seems more appropriate for your requirements.

Related

Find closest match from 2 columns in postgresql

I have a table "ways" containing coordinates (lat/lon) values. Suppose I have a coordinate (x,y) and I want to check the closest match from the table ways. I have seen some similar questions like this: Is there a postgres CLOSEST operator?
However in my case I have 2 columns instead of 1. Is there a query to do something like this this ?
You could store the data as PostGIS 'point' type instead of coordinate values:
https://postgis.net/docs/ST_MakePoint.html
https://postgis.net/docs/ST_GeomFromText.html
This would empower you with all the PostGIS functionality such as:
https://postgis.net/docs/ST_DWithin.html
Then you could create a GiST index and use the PostGIS <-> operator to take advantage of index assisted nearest neighbor result sets. The 'nearest neighbor' functionality is pretty common. Here is a great explanation:
https://postgis.net/workshops/postgis-intro/knn.html
“KNN” stands for “K nearest neighbours”, where “K” is the number of neighbours you are looking for.
KNN is a pure index based nearest neighbour search. By walking up and down the index, the search can find the nearest candidate geometries without using any magical search radius numbers, so the technique is suitable and high performance even for very large tables with highly variable data densities.

How to do in-memory search for polygons that contain a given point?

I have a PostGreSQL table that has a geometry type column, in which different simple polygons (possibly intersecting) are stored. The polygons are are all areas within a city. I receive an input of a point (latitude-longitude pair) and need to find the list of polygons that contain the given point. What I have currently:
Unclustered GiST index defined on the polygon column.
Use ST_Contains(#param_Point, table.Polygon) on the whole table.
It is quite slow, so I am looking for a more performant in-memory alternative. I have the following ideas:
Maintain dictionary of polygons in Redis, keyed by their geohash. Polygons with same geohash would be saved as a list. When I receive the point, calculate its geohash and trim to a desired level. Then search in the Redis map and keep trimming the point's geohash until I find the first result (or enough results).
Have a trie of geohashes loaded from the database. Update the trie periodically or by receiving update events. Calculate the point's geohash, search in the trie until I find enough results. I prefer this because the map may have long lists for a geohash, given the nature of the polygons.
Any other approaches?
I have read about libraries like GeoTrie and Polygon Geohasher but can't seem to integrate them with the database and the above ideas.
Any cues or starting points, please?
Have you tried using ST_Within? Not sure if it meets your criteria but I believe it is meant to be faster than st_contains

MongoDB/PyMongo geospatial query: distance of documents from a point

I've recently upgraded my MongoDB from version 2.2.1 to version 2.4.6, and pymongo to 2.6.2.
One of the reasons for the upgrade is the capability of the new version of MongoDB to calculate and return the distance of the documents (which include proper coordinates) from the center of a geospatial query as explained here.
So far I execute the following query:
db.collection.find({"loc": {"$within": {"$center": [[LON, LAT], RADIUS]}}})
where LON, LAT and Radius are proper numbers. I then programmatically calculate the distance from the center for each document returned.
Now I'm trying to have MongoDB to do the distance calculations on my behalf, because of higher efficiency compared to my code.
What I'm trying now is the following:
db.collection.find({"loc": {"$geoWithin": {"$centerSphere": [[LON, LAT], RADIUS]}}})
where RADIUS is now calculated properly (radius in km / 6371), but I get the same results as the older query.
How should I change the new query in order to get returned the extra field "dis" per every document returned?
The geospatial index is 2D, which should work according to docs, but I can change it to 2dsphere if necessary. Does anyone have a good suggestion?
Try using the $geoNear command in the aggregation framework. The $geoNear documentation is here:
http://docs.mongodb.org/manual/reference/aggregation/geoNear/
Your query will end up looking like:
db.collection.aggregate([{$geoNear:{near:[LON,LAT],distanceField:"distance",maxDistance:RADIUS,spherical:true}}])
and the resulting documents will have a field named "distance" with the calculated value. Hope that helps.

Which PostGIS SRID is most efficient for a spatial index?

I have a PostGIS-enabled database with a table called locations that stores latitude-longitude points (SRID 4326) in a column called coordinates. However, all of my lookups on that table convert the points to a metric projection (SRID 26986) mainly to do distance comparisons.
Obviously I'd like to create a spatial index on the coordinates column. My question is, which is the best (most computationally efficient) SRID to use in the coordinates spatial index in this case?
I can either index using SRID 4326...
CREATE INDEX locations_coordinates_gist
ON locations
USING GIST (coordinates);
Or using SRID 26986...
CREATE INDEX locations_coordinates_gist
ON locations
USING GIST (ST_Transform(coordinates, 26986));
I discovered this helpful information reading the PostGIS documentation on the ST_Transform function...
If using more than one transformation, it is useful to have a
functional index on the commonly used transformations to take
advantage of index usage.
So it seems the answer is, use both! I have created two indices, one with each SRID.

Is Mongodb geohaystack the same with standard mongodb spatial index?

It seems that mongodb has 2 types of geospatial index.
http://www.mongodb.org/display/DOCS/Geospatial+Indexing
The standard one. With a note:
You may only have 1 geospatial index per collection, for now. While
MongoDB may allow to create multiple indexes, this behavior is
unsupported. Because MongoDB can only use one index to support a
single query, in most cases, having multiple geo indexes will produce
undesirable behavior.
And then there is this so called geohaystack thingy.
http://www.mongodb.org/display/DOCS/Geospatial+Haystack+Indexing
They both claim to use the same algorithm. They both turn earth into several grids. And then search based on that.
So what's the different?
Mongodb doesn't seem to use Rtree and stuff right?
NB: Answer to this question that How does MongoDB implement it's spatial indexes? says that 2d index use geohash too.
The implementation is similar, but the use case difference is described on the Geospatial Haystack Indexing page.
The haystack indices are "bucket-based" (aka "quadrant") searches tuned for small-region longitude/latitude searches:
In addition to ordinary 2d geospatial indices, mongodb supports the use
of bucket-based geospatial indexes. Called "Haystack indexing", these
indices can accelerate small-region type longitude / latitude queries
when additional criteria is also required.
For example, "find all restaurants within 25 miles with name 'foo'".
Haystack indices allow you to tune your bucket size to the distribution
of your data, so that in general you search only very small regions of
2d space for a particular kind of document. They are not suited for
finding the closest documents to a particular location, when the
closest documents are far away compared to bucket size.
The bucketSize parameter is required, and determines the granularity of the haystack index.
So, for example:
db.places.ensureIndex({ pos : "geoHaystack", type : 1 }, { bucketSize : 1 })
This example bucketSize of 1 creates an index where keys within 1 unit of longitude or latitude are stored in the same bucket. An additional category can also be included in the index, which means that information will be looked up at the same time as finding the location details.
The B-tree representation would be similar to:
{ loc: "x,y", category: z }
If your use case typically searches for "nearby" locations (i.e. "restaurants within 25 miles") a haystack index can be more efficient. The matches for the additional indexed field (eg. category) can be found and counted within each bucket.
If, instead, you are searching for "nearest restaurant" and would like to return results regardless of distance, a normal 2d index will be more efficient.
There are currently (as of MongoDB 2.2.0) a few limitations on haystack indexes:
only one additional field can be included in the haystack index
the additional index field has to be a single value, not an array
null long/lat values are not supported
Note: distance between degrees of latitude will vary greatly (longitude, less so). See: What is the distance between a degree of latitude and longitude?.