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.
Related
I have a collection with a nested array of polygons stored in the below given format:
_id: ObjectId("...."),
"attributes": {
"zones": [
{
"zoneName": "...",
"zoneLocs" : [
{
"type" : "Polygon",
"coordinates" : [[...]]
}
....
]
}
....
]
}
I want to perform a geojson search on this collection, where I pass a point and a max-distance value, and pull all the documents which have a polygon in the enclosed area.
I tried to do this by using $elemMatch, $geoWithin and $center. My final query looked like this, but did not fetch any results, even though there were polygons in the enclosing area:
{
"attributes.zones": {
"$elemMatch":{
"zoneLocs": {
"$elemMatch" : {
"$geoWithin": {
"$center" : [
[
-104.84127910390623,
39.820705065855044
],
100000
]
}
}
}
}
}
}
I have created a 2dsphere index on the path 'attributes.zones.zoneLocs', but no luck so far. Any help would be greatly appreciated.
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 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).
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