$geoWithin query fail to retrieve point included in the queried polygon - v2 - mongodb

I've already ask the same question in this post. My example was subject to earth curvature issue so lets have a look to another one.
This time I have two nested polygons. A large one and a smaller one. Performing a $geoWithin query with the larger one return no document while the document is found using the smaller polygon. Any thoughts?
https://mongoplayground.net/p/V_3-s-itngA
The document I'm trying to query which is located on an island on France west coast.
{
"_id": {
"$oid": "625fec0f6476793a4581d172"
},
"featureOfInterest": {
"samplingFeature": {
"geometry": {
"type": "Point",
"coordinates": [
-2.3433781679840138,
46.713764788942484
]
},
"name": [
{
"lang": "en",
"text": "France"
}
],
"type": "Feature"
}
}
}
And the query
db.collection.aggregate([
{
$match: {
"$or": [
//Largest polygon - return no document
{
"samplingFeature.geometry": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[[-55.722656,34.161818],[58.007813,34.161818],[ 58.007813,53.540307],[ -55.722656, 53.540307], [-55.722656,34.161818]]]
}
}
}
},
//Smallest polygon - return the document
//{
// "samplingFeature.geometry": {
// "$geoWithin": {
// "$geometry": {
// "type": "Polygon",
// "coordinates": [[[-5.800781, 42.682435], [9.316406, 42.682435], [9.316406, 50.625073], [-5.800781, 50.625073], [-5.800781, 42.682435]]]
// }
// }
//}
//}
]
}
}
])

You've bent the planet other way round. The coordinates in your post make these boxes:
the marker is clearly outside the the larger box.
Please use the link to jsfddle in my answer to your previous question instead of globes, or wherever you get your image from. The shortest path between 2 points far away does not necessarily follow longitudes and latitudes. Please read about the math of Geodesic calculations used in mongo geospatial queries.

Related

$geoWithin query fail to retrieve point included in the queried polygon

I'm trying to query a document using its location with two polygons that are quite similar. Both includes the location of the document but one finds it and the other not. I thought that this was related to "big polygons" but I managed to reduce the polygons enough to rule out this possibility. See previous post. Any idea explaining such a difference?
Playground: https://mongoplayground.net/p/sTEtYD3HU8m:
Document:
{
"_id": {
"$oid": "63ef9379e671073bfb963145"
},
"geometry": {
"type": "Point",
"coordinates": [
2.834,
47.264
]
},
"_class": "org.example.springdatamongodbgeowithinissue.model.SamplingGeometry"
}
Is not in search results for this polygon:
{
"geometry": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[
[
-16.1,
49.12
],
[
-16.1,
46.156
],
[
16.1,
46.156
],
[
16.1,
49.12
],
[
-16.1,
49.12
]
]
]
}
}
}
}
Still the same issue with Earth's curvature. Your area is long enough to take it into account:
zooming in and's clearly outside:
The map: https://jsfiddle.net/blex18/w9g4bzyk/1/
var map = new google.maps.Map(document.body, {zoom:5,center:{lat:47.264,lng:2.834}});
new google.maps.Polygon({geodesic:true,map:map,geodesic:true,
path:[
{lat:49.12,lng:-16.1},
{lat:46.156,lng:-16.1},
{lat:46.156,lng:16.1},
{lat:49.12,lng:16.1},
{lat:49.12,lng:-16.1}]});
new google.maps.Marker({
position: {lat:47.264,lng:2.834},
map,
title: "Here",
});

Mongodb aggregate on two collections based on geopoint

I have two collections
person
{
"name": "Mike",
"age": 42,
"address": {
"location": {"type": "Point", "coordinates": [12.3456, 78.9101]}
}
}
restaurant
{
"name": "Bistro",
"type": ["Maxican", "Italian"],
"location": {"type": "Point", "coordinates": [12.3555, 78.9333]}
}
I've created spherical indexes on both collections
db.person.createIndex({"address.location": "2dsphere"})
db.restaurant.createIndex({"location": "2dsphere"})
Now I want to find all the restaurants near to a person using lat/long in both collections.
for e.g find all the restaurants within 10KM of a person. result will look like below
{
"name": "Mike",
"age": 42,
"address": {
"location": {"type": "Point", "coordinates": [12.3456, 78.9101]}
},
"nearby_restaurants": [{"name": "Bistro", "distance": 5.3}] // this means bistro is 5.3 KM away from this person
}
Notice that, I'm only using name field from restaurant collection and an additional field distance which will be calculated after the query.
I want to do this for all person. so basically for each person, i have to scan the whole restaurant collection every time.
To achieve this I thought of using lookup with aggregate, something like below
db.person.aggregate([
{
$lookup: {
from: "restaurant",
let: {"personPoint": "$address.location"},
as: "nearby_restaurants",
pipeline: [
{
$geoNear: {
near: "$$personPoint",
spherical: true,
distanceField: "distance",
maxDistance: 10 * 1000, // within 10 KM
distanceMultiplier: 0.001 // get the result in KM
}
},
{
$unwind: "$location"
},
]
}
},
{
$unwind: {
path: "$nearby_restaurants",
preserveNullAndEmptyArrays: true
}
}
])
This doesnt work at all. I get this error: $geoNear requires a 'near' option as an Array"
I tried to look at different sources but couldnt understand and fix the error.
PS: If currently, it's not possible through lookups/aggregate, how can we achieve the same through looping over each person's document?

Query to calculate a percentage of a GEO surface in a radius

I am GeoJSON unfortunately still a bloody beginner. Now I have to solve a problem and understand, unfortunately, no piece of systematics.
Can you please help me and explain how I can use MongoDB to evaluate GEO data for the following case.
We have three areas (for example, countries), these have a value (say base area) now I have a catchment area that covers all three countries in part. How do I get the percentage of each country?
Here is a graphic to visualize the problem:
It is needed here e.g. the areas of A (n), B (n) and C (n).
In the database (mongodb#3.2) I have corresponding document with GEO data. Example:
{
"type": "FeatureCollecton",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
13.6868862,
51.063946
],
[
13.6873401,
51.063999
],
[
13.6883277,
51.0640888
],
...
]
]
},
"properties": {
"name": "Land A",
"qkm": 65.866862
}
},
]
}, ...

Query to exclude the polygon which lying on given coordinate

I want to try to use geoIntersects query and the result returns all the polygon which intersect with the given coordinate. Here my requirement is that I don't want to include that polygon which edge are coinciding with the given coordinates .
{ "geometry": {
"$geoIntersects": {
"$geometry": {
"type": "Polygon",
"coordinates": coordinate
}
}
}}
You can use the $not operator to select the documents that do not intersect with the given coordinate.
{ "geometry": {
"$not": {
"$geoIntersects": {
"$geometry": {
"type": "Polygon",
"coordinates": coordinate
}
}
}
}}

Query to Match a Polygon that contains a Point

The documents in my mongodb collection look like this:
{
"_id" : ObjectId("5562d6831683523f449e7d85")
"geometry" : {
"type" : "Polygon",
"coordinates" :
[[
[-122.4,37.81],
[-132.9, 39.9],
[-122.28, 37.80],
[-124.18, 39.81]
]]
}}
I have a point (lat long pair), which I'll call x and y. I need to see if the coordinates of the document create a polygon such that these coordinates are inside that polygon.
So, of course I need to compute the line describing each edge of the polygon, etc., and then see if the coordinates of the point are within that. However, for now, let's just assume we want to query documents that have x and y within the maximum and minimum lat long values of the entire array.
Here is how I tried to query this:
db.<collection-name>.find(
{'geometry.coordinates':
{$elemMatch:
{
[{$gt:-122.1}, {$lt:-122.0 }], [{$gt: 37.89 },{$lt: 37.91}]
}
}
}
)
however, the result is: Unexpected token [. I tried to follow the example here.
How do I query an array like this, where there are conditions on each element of the array in the document? thanks.
What you seem to be trying to do by matching array elements is actually "Finding a Polygon that contains a Point", which is why I changed your question title.
To accomplish this you are better off using the geoSpatail features of MongoDB rather than trying to work out the bounds yourself. With valid GeoJSON data the query is quite simple using the $geoIntersects operator.
To demonstrate, I'll first set up a collection, with some Polygon data:
db.areas.insert([
{
"name": "San Jose",
"geometry": {
"type": "Polygon",
"coordinates": [[
[ -122.20916748046876, 37.13404537126446 ],
[ -122.20916748046876, 37.496652341233364 ],
[ -121.65710449218749, 37.496652341233364 ],
[ -121.65710449218749, 37.13404537126446 ],
[ -122.20916748046876, 37.13404537126446 ]
]]
}
},
{
"name": "San Franciso",
"geometry": {
"type": "Polygon",
"coordinates": [[
[ -122.73651123046874, 37.58811876638322 ],
[ -122.73651123046874, 37.89219554724437 ],
[ -122.28332519531249, 37.89219554724437 ],
[ -122.28332519531249, 37.58811876638322 ],
[ -122.73651123046874, 37.58811876638322 ]
]]
}
}
])
Then ( though not required for $geoIntersects specifically ) when working with geoSpatial data it is best to have an "index" defined. The one that makes sense for real GeoJSON locations is "2dsphere". The index is created on the field that contains the "root" of the GeoJSON data, which is in this case called "geometry":
db.areas.createIndex({ "geometry": "2dsphere" })
Then all you need to do is supply a .find() query. I'm using the coordinates for "San Francisco city" here:
db.areas.find({
"geometry": {
"$geoIntersects": {
"$geometry": {
"type": "Point",
"coordinates": [
-122.45361328124999,
37.76420119453823
]
}
}
}
})
Which of course returns the "Polyon" defining the "San Franciso" area since that "Point" lies within that object.
{
"name": "San Franciso",
"geometry": {
"type": "Polygon",
"coordinates": [[
[ -122.73651123046874, 37.58811876638322 ],
[ -122.73651123046874, 37.89219554724437 ],
[ -122.28332519531249, 37.89219554724437 ],
[ -122.28332519531249, 37.58811876638322 ],
[ -122.73651123046874, 37.58811876638322 ]
]]
}
}
That is all there is to finding whether your "Point" lies within a "Polygon" you have stored in your collection.
Also look at tools such as geojsonlint.com and geojson.io (examples, not endorsements) in order to validate and visualise your data, which from your example does not provide a well formed Polygon.