[SERVER-37043] Allow multi ringed shapes to be used for $geoWithin. Created: 07/Sep/18  Updated: 27/Dec/23

Status: Backlog
Project: Core Server
Component/s: Geo
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Christoph Strobl Assignee: Backlog - Query Integration
Resolution: Unresolved Votes: 0
Labels: qi-geo
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
Assigned Teams:
Query Integration
Participants:

 Description   

Add a way to specify minDistance to $geoWithin allowing querying for being in a ring shape, analogous to what $near/$nearSphere allowed with $minDistance and $maxDistance options.

The only current workaround if $geoNear aggregation stage cannot be used is this query:

{$and:[
  {$nor:[
     {center:{
        $geoWithin:{$centerSphere:[ [ <x>,<y> ],<minDistance-in-radians>]}
     }}
  ]}, 
  {center:{
        $geoWithin:{$centerSphere:[ [ <x>, <y> ],<maxDistance-in-radians>]}
  }}
]} 

 

Original description:

With the deprecation of count in favor of countDocuments it is no longer possible to use the $near operator with the new API.

Unfortunately the alternative $geoWithin $center only supports radius whereas $near allowed having a ring specified by $minDistance & $maxDistance.

There's no workaround for this, $geoWithin seems to only supports single ringed structures, so this might be more a server issue than a driver one.



 Comments   
Comment by Ana Meza [ 29/Mar/22 ]

Agreed during triage to send to Backlog 

Comment by Asya Kamsky [ 23/Oct/18 ]

P.S. I think 4. is just driver work since I think $geoNear already has all the options to emulate $match with $near or $nearSphere.

 

Comment by Asya Kamsky [ 23/Oct/18 ]

cstrobl I understand the issue now.

There are two ways to express $near to countDocuments but neither of them is a straight transformation of existing syntax. For reference, one is $geoNear agg stage, the other is compound $and query with two $geoWithin clauses, one finding all within maxDistance the other negating all within minDistance.

On our side we need to consider a number of options (some of them are already "in effect"):

  1. forbid $where, $near, & $nearSphere in countDocuments on driver or server and force user to re-write them - this is effectively what we did with initial introduction of the new helper. User must either: re-write the filter, rewrite the count as aggregation, or they can use the deprecated but still available count command the behavior & performance of which hasn't changed, and they are fine as long as they don't try to use it inside transactions.
  2. the driver rewrites the countDocuments helper rather than requiring the user to do so. This could be tricky and complicated and it doesn't get us any closer to getting the user to stop using no longer supported in this context operators.  It will also not be possible for $where in some cases, and may not be easily doable (programmatically) in cases where it is possible.
  3. the server adds new options to $geoWithin to sufficiently support re-writing $near and $nearSphere to $geoWithin - either user or driver still have to re-write the queries.  Does not solve $where.
  4. the server adds new options to $geoNear aggregation stage to create equivalent options; driver still has to take a special case path to rewrite $near/$nearSphere filter as $geoNear rather than $match. Does not solve $where.

In all above cases user can be the enduser or the framework built on top of the driver.

While there is definite value in additional options/flexibility for $geoNear aggregation stage, the issue remains that $near, $nearSphere and  $geoNear are all strange "filters" because they contain both a "$match" and a "$sort" which means they can't really be rewritten to be just a $match stage in a non-lossy way (this particular case is special only because we know we are just counting, but that won't be knowable in the more general case).

This ticket will continue to track the ability to specify minDistance option to $geoNear agg stage while we discuss other issues brought up in discussion here.

Comment by Christoph Strobl [ 23/Oct/18 ]

The java driver offers dedicated count methods taking a Bson filter query. This query is wrapped in $match to be run as aggregation.
Having a filter query use one of the geo operators results in an error Command failed with error 2 (BadValue): $geoNear, $near, and $nearSphere are not allowed in this context.

 
MongoClient client = MongoClients.create(settings);
MongoCollection<org.bson.Document> collection = client.getDatabase("test").getCollection("test");
Bson nearSphereFilter = Filters.nearSphere("location", new Point(new Position(-73.99D, 40.73D)), 0.313D, 0D);
 
// { "count": "test",
//  "query": { "location" : { "$nearSphere" : { "$geometry" : { "type" : "Point", "coordinates" : [-73.99, 40.73] }, "$maxDistance" : 0.313, "$minDistance" : 0.0 } } },
//  "$db": "test",
//  ...
collection.count(nearSphereFilter); // the deprecated count method
 
// { "aggregate": "test",
//   "pipeline": [
//     {
//       "$match": { "location": { "$nearSphere": { "$geometry": { "type": "Point", "coordinates": [-73.99,40.73] }, "$maxDistance": 0.313, "$minDistance": 0 } } }
//     },
//     {
//       "$group": { "_id": null, "n": { "$sum": 1 } }
//     }
//   ],
//   "$db": "test"
//  ...
collection.countDocuments(nearSphereFilter); // new count method - errors

Using a $geoWithin $center filter works but lacks minDistance.

 
Bson geoWithinFilter = Filters.geoWithinCenterSphere("location", 73.99D, 40.73D, 0.313D);
 
// { "aggregate": "test",
//   "pipeline": [
//     {
//       "$match": { "location" : { "$geoWithin" : { "$centerSphere" : [ [73.99, 40.73], 0.313] } } }
//     },
//     {
//       "$group": { "_id": null, "n": { "$sum": 1 } }
//     }
//   ],
//   "$db": "test"
//  ...
collection.countDocuments(geoWithinFilter); // new count method - works

Comment by Asya Kamsky [ 22/Oct/18 ]

cstrobl can you clarify the limitation here?

$geoNear aggregation stage has supported minDistance as well as maxDistance since 3.2.

 

Generated at Thu Feb 08 04:44:48 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.