$geoWithin and $centerSphere with dynamic radius

So, imagine these input documents:

[
  {
    "location": {
      "type": "Point",
      "coordinates": [
        10,
        20
      ]
    },
    "proximity": 0.001
  },
  {
    "location": {
      "type": "Point",
      "coordinates": [
        10,
        30
      ]
    },
    "proximity": 0.005
  }
]

When I want to filter with $geoWithin and $centerSphere, if I specify static radius, the query works:

db.collection.aggregate([
  {
    "$match": {
      "location": {
        "$geoWithin": {
          "$centerSphere": [
            [
              10,
              20
            ],
            0.001
          ]
        }
      }
    }
  }
])

However, when I set radius dynamically based on some property, the query throws an error:

db.collection.aggregate([
  {
    "$match": {
      "location": {
        "$geoWithin": {
          "$centerSphere": [
            [
              10,
              20
            ],
            "$proximity"
          ]
        }
      }
    }
  }
])

The error thrown is: radius must be a non-negative number. What’s happening here?

I created this playground for testing.

Hi @NeNaD

I believe it’s because $centerSphere requires an actual number. When you put "$proximity" there, it treats it as a string. I know you intend it to refer to a specific document field, but I don’t think it has that feature.

Alternatively perhaps you can do something like:

const proximity = 0.001;
...
          "$centerSphere": [
            [
              10,
              20
            ],
            proximity
          ]
...

where proximity is defined as a variable outside of the aggregation. Not sure if your use case allows this, but this is one way I can think of to make it work.

Best regards
Kevin

1 Like

Hi @kevinadi,

Thanks for the answer! :smiley:

I think it should accept it, since it’s aggregate query, right? :sweat_smile:

Yeah, I can not have static proximity since it has to be fetched on document level from proximity field.

Specifically in the case of $centerSphere, at least in my mind it does make sense to not be able to reference things: $centerSphere is basically describing a circle on a certain position with a certain radius, and the query reads like: “find me all documents that is within this circle”.

However referencing a field in a document would mean that the circle can be made variable based on each document in the collection, so you’re basically running one $centerSphere query for each document in the collection, isn’t it? :slight_smile:

Best regards
Kevin

1 Like

That is correct. :smiley:

That is what I need in this case though. Both static and dynamic use cases are useful, and I just though that this can be dynamic inside aggregate.

Another way to solve this is to add new property field where I would calculate distance for each document, and then add another stage where I would compare new distance field with proximity field. But, I don’t know how to calculate the distance. Do you happen to know how do to it?

I created this post for it, so please add solution there if you know the solution. :smiley: