I have a document in the database that contains a "polygon" property that, as far as I can tell, is a valid GeoJSON object. I want to search the database using a GeoJSON Point object to find documents where the polygon in the polygon property contains the Point. To do so, I am using the $geoIntersects operator, however, whenever I preform the find, MongoDB returns the error: [Error: Can't use $geoIntersects].
The only object in the database:
{
"_id": ObjectId("581540795fd2da1b188eb09c"),
"name":"String",
"polygon":{
"coordinates":[
[ -90, -180 ],
[ 90, -180 ],
[ 90, 180 ],
[ -90, 180 ],
[ -90, -180 ]
],
"_id": ObjectId("581540795fd2da1b188eb09d"),
"name": "String",
"type": "Polygon"
},
"__v":0
}
I am using mongoose to search the database. The query that is used to preform the search:
{
polygon: {
$geoIntersects: {
$geometry: {
type: 'Point',
coordinates: [<long>, <lat>]
}
}
}
}
If I set the latitude and longitude to something simple, say (0, 0) or (1, 1). It returns the error. According to what I read elsewhere, the only reason this error should be returned is because the documents in the database are not valid GeoJSON objects, but I cannot see anything wrong with the only object in the database.
I think you're missing the outer array on your coordinates for a geoJSON polygon. Your document should look like this:
{
"_id": ObjectId("581540795fd2da1b188eb09c"),
"name":"String",
"polygon":{
"coordinates":[[
[ -90, -180 ],
[ 90, -180 ],
[ 90, 180 ],
[ -90, 180 ],
[ -90, -180 ]
]],
"_id": ObjectId("581540795fd2da1b188eb09d"),
"name": "String",
"type": "Polygon"
},
"__v":0
}
From the geoJSON spec, http://geojson.org/geojson-spec.html#id4
Coordinates of a Polygon are an array of LinearRing coordinate arrays. The first element in the array represents the exterior ring. Any subsequent elements represent interior rings (or holes).
Related
It's been now 8 hours I'm trying to deal with a MongoDB Geojson $geoIntersects issue :
It's working very well when my polygon is a square, or a rectangle,
but I'm unable to get some results from a $geoIntersects request when my Polygon has crossing vertices, like this example :
(Image from (https://geoman.io/geojson-editor))
The polygon data looks like this :
{
"type": "Feature",
"properties": {
"shape": "Polygon"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-1.565584, 47.226352],
[-1.564704, 47.226927],
[-1.564093, 47.225616],
[-1.563138, 47.226374],
[-1.565584, 47.226352]
]
]
},
"id": "dda54a42-090b-46ea-9dd0-fdda6d240f90"
}
For this example, I need to know if the Polygon includes my Point coordinates.
This is my simple query :
db.geojsondatas.find({
geometry: {
$geoIntersects: {
$geometry: {
type: "Point",
coordinates: [ -1.555638, 47.216245 ]
}
}
}
});
Anyone knows if there is a way to do this ?
Thanks by advance.
Maybe try with JTS Topology Suite and investigate your polygon:
I don't think $geoIntersects supports Self-intersecting polygon.
I want to get point within a polygon and I am using below query for getting data
loc: {
$geoWithin: {
$geometry: {
type: 'Polygon',
coordinates: [
[
[
-117.83736,
33.73838
],
[
-117.83588,
33.73837
],
[
-117.83369,
33.73839
]...
]
]
}
}
}
But I am getting an error like
Edges 1 and 3 cross. Edge locations in degrees:
How can I solve this?
As i stated in the comments your coordinates list is an invalid polygon.
You need to validate each edge with every other edge using a simple check as described here.
I have a single Azure Cosmos DB collection I am querying against, hoping to use Geo-spatial index for efficient queries. The problem I'm encountering is that the RU consumption seems inefficient.
The collection has only 50k 1kb documents in it, but a query using ST_DISTANCE returning a single document consumes >900 RUs.
I've seen the RUs scale linearly based on the # of documents in the collection. It would seem indexing should prevent this behavior.
Example Query (950 RUs):
SELECT * FROM c where ST_DISTANCE(c.location, { 'type': 'Point', 'coordinates': [34.69, -1.91] }) < 500
Example document:
[
{
"id": "1504891036",
"name": "Oujda",
"location": {
"type": "Point",
"coordinates": [
34.69,
-1.91
]
},
"population": 409391,
"country": "Morocco",
"country.iso2": "MA",
"country.iso3": "MAR",
}
]
I've not modified the default indexing policy, which seems to cover spatial indexing:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*",
"indexes": [
{
"kind": "Range",
"dataType": "Number",
"precision": -1
},
{
"kind": "Range",
"dataType": "String",
"precision": -1
},
{
"kind": "Spatial",
"dataType": "Point"
}
]
}
],
"excludedPaths": []
}
I determined the problem. I had transposed the longitude and the latitude coordinate prescribed by GeoJSON:
Cosmos is expecting:
"location": {
"type": "Point",
"coordinates": [
<#lon>,
<#lat>
]
I had assumed, incorrectly, that it was lat/lon. Therefore many of my latitudes were outside of the 90/-90 range required, since longitude can be 180/-180. After re-creating my ~50k documents, RU for coordinate based lookups are consistently <10 RUs.
Before fix (all docs have transposed lat/lon coordinates, many outside the 90/-90 bounds and therefore invalid):
SELECT * FROM c where ST_DISTANCE(c.location, { 'type': 'Point', 'coordinates': [34.69, -1.91] }) < 500
940 RUs, 1 document returned
After fix (all docs re-created with lat/lon set correctly per GeoJSON specs):
SELECT * FROM c where ST_DISTANCE(c.location, { 'type': 'Point', 'coordinates': [-1.91,34.69] }) < 500
6 RUs, 1 document returned
Initial issue was confirmed/diagnosed by the following query:
SELECT ST_ISVALIDDETAILED(c.location) FROM c where c.name = "Kansas City"
Error: "Latitude values must be between -90 and 90 degrees."
I’m trying to do a spatial query against DocumentDB that looks like this:
SELECT * FROM root r WHERE
ST_WITHIN({'type':'Point','coordinates':[-122.02625, 37.4718]}, r.boundingBox)
to match a document that looks like this in the collection:
{
"userId": "747941cfb829",
"id": "747941cfb829_1453640096710",
"boundingBox": {
"type": "Polygon",
"coordinates": [
[-122.0263, 37.9718],
[-122.0262, 37.9718],
[-122.0262, 36.9718],
[-122.0263, 36.9718],
[-122.0263, 37.9718]
]
},
"distance": 0,
"duration": 1
}
I’ve turned on spatial indexes ala https://azure.microsoft.com/en-us/documentation/articles/documentdb-geospatial/ but I’m not getting a match back from DocumentDB.
Any ideas?
NOTE: Corrected GeoJson coordinate order.
The correct specification of a GeoJSON polygon has an additional array around the coordinates than you show to allow for the possibility of holes and multipolygons. So, it would look like this:
{
"type": "Polygon",
"coordinates": [
[
[0, 0], [10, 10], [10, 0], [0, 0]
]
]
}
My data looks something like this:
{
"id": "a06b42cf-d130-459a-8c89-dab77966747c",
"propertyBag": {
"Fixed": {
"address": {
"locationName": "",
"addressLine1": "1 Microsoft Way",
"addressLine2": null,
"city": "Redmond",
"postalCode": "98052",
"subDivision": null,
"state": "WA",
"country": "USA",
"location": {
"type": "Point",
"coordinates": [
47.640049,
-122.129797
]
}
},
}
}
}
Now when I try to query something like this
SELECT * FROM V v
WHERE ST_DISTANCE(v.propertyBag.Fixed.address.location, {
"type": "Point",
"coordinates": [47.36, -122.19]
}) < 100 * 1000
The results are always empty. I was wondering if someone can please let me know what maybe wrong?
I suspect that you just have the logitude and latitude transposed. Because if I change the document to:
"location": {
"type": "Point",
"coordinates": [-122.129797, 47.640049]
}
And I run this query:
SELECT
ST_DISTANCE(v.propertyBag.Fixed.address.location, {
"type": "Point",
"coordinates": [-122.19, 47.36]
})
FROM v
I get a result, but if I run it the way you show, I get no results.
In GeoJSON, points are specified with [longitude, latitude] to make it match with our normal expectations of x being east-west, and y being north-south. Unfortunately, this is the opposite of the traditional way of showing GEO coordinates.
-122 is not a valid value for latitude. The range for latitude is -90 to +90. Longitude is specified -180 to +180.
If your database is already populated and you don't feel like migrating it, then you could use a user defined function (UDF) to fix it during the query but I would strongly recommend doing the migration over this approach because geo-spacial indexes won't work as you have it now and your queries will be much slower as a result.
Again, I don't recommend this unless a GEO index is not important, but here is a swapXY UDF that will do the swap:
function(point) {
return {
type: "Point",
coordinates: [point.coordinates[1], point.coordinates[0]]
};
}
You use it in a query like this:
SELECT * FROM v
WHERE
ST_DISTANCE(
udf.swapXY(v.propertyBag.Fixed.address.location),
udf.swapXY({
"type": "Point",
"coordinates": [47.36, -122.19]
})
) < 100 * 1000