Hi Nick,
We agree that this is not expected behavior, but it is indeed the response from MongoDB. I created BeanMetadata and a DataObject with your specified Point. I issued a query using LEAF’s Java API:
Polygon bbox = Polygon.newBuilder()
.withExterior(List.of(
Position.of(0.849607, 43.447224),
Position.of(23.23242, 43.447224),
Position.of(23.23242, 49.873922),
Position.of(0.849607, 49.873922),
Position.of(0.849607, 43.447224)
))
.build();
DataObjectQuery query1 = dataObjectQuery(types("GeoType"), geoWithin("location", bbox));
List<DataObject> results1 = dataObjectService.load(query1, Context.makeSystemContext());
And the DataObject with your outside Point coordinate was unexpectedly returned as a result. Changing its latitude to 50.5 places it sufficiently outside the bounding Polygon that it is no longer returned.
I directly queried the MongoDB database with the equivalent Mongo query:
{
"$and": [
{
"location": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[
[ 0.849607, 43.447224],
[23.23242, 43.447224],
[23.23242, 49.873922],
[ 0.849607, 49.873922],
[ 0.849607, 43.447224]
]
]
}
}
}
},
{
"type": {
"$in": [
"GeoType"
]
}
}
]
}
And, sure enough, Mongo returns this DataObject, which is unquestionably outside that bounding rectangular Polygon. I’ve confirmed the same results whether the location field is indexed or not (LEAF creates a 2dsphere index). And I have confirmed that you specified the positions of the bounding Polygon in the correct counter-clockwise order. I tested with MongoDB 4.0 and 4.2.
I tried your mitigation technique - adding additional points to the bounding Polygon - and directly queried MongoDB:
"coordinates": [
[
[ 0.849607, 43.447224],
[10.0, 43.447224],
[20.0, 43.447224],
[23.23242, 43.447224],
[23.23242, 49.873922],
[20.0, 49.873922],
[10.0, 49.873922],
[ 0.849607, 49.873922],
[ 0.849607, 43.447224]
]
]
…and now your outside-Point is correctly excluded!
LEAF relies on the database for geospatial querying, and in this case - as best as we’re able to tell - it appears as if Mongo’s $geoWithin query operator is inaccurate with some edge cases.
I switched to a SQL-backed LEAF data service, and - with the original code - your outside Point is correctly excluded.
We’ll investigate further to see if we can come up with a more satisfactory explanation for MongoDB’s behavior here, but in the meantime it looks like its accuracy may be related to the sparseness of the bounding Polygon, and your mitigation - defining additional positions when covering large areas, even for a rectangle(!) - is advised. Or, if it meets your application’s requirements, you may wish to use a SQL database backed DataObjectService (eg: PostgreSQL) instead.