mongodbmongodb-querygeolocation

MongoDB query for points with cutout


In my lootPoint collection I have the data like this:

{
    "_id" : "1856132932",
    "point" : {
        "type" : "Point",
        "coordinates" : [ 
            21.6550408, 
            50.1034841
        ]
    }
}

{
    "_id" : "2184534902",
    "point" : {
        "type" : "Point",
        "coordinates" : [ 
            21.6560194, 
            50.1037961
        ]
    }
}

I want to query for a random point, matching the square with the circular 20m cut-out in the middle:

enter image description here

Using Internet and AI I managed to assemble the following:

db.lootPoint.aggregate([
  {
    $match: {
      "point.coordinates": {
        $geoWithin: {
          $geometry: {
            type: "Polygon",
            coordinates: [
              [
                  [21.654939727403415,50.10333291665514],
                  [21.656736672596585,50.10333291665514],
                  [21.656736672596585,50.10453288334485],
                  [21.654939727403415,50.10453288334485],
                  [21.654939727403415,50.10333291665514]
              ]
            ]
          }
        },
        $not: {
          $geoWithin: {
            $centerSphere: [[21.6558382, 50.1039329], 20 / 3963.2]
          }
        }
      }
    }
  },
  { $sample: { size: 1 } }
])

Upon running this command in Robo3T I'm getting the error: can't parse field $not...

I tried re-writing the query like with $and and $not so:

db.lootPoint.aggregate([
  {
    $match: {
      $and:[
        { "point.coordinates": {...} },
        { "point.coordinates": { $not:[ ... ] } },
      ]
    }
  },
  ...

but it brings up 0 results.

What am I doing wrong? How to make this query valid? Are there any alternative approaches?


Solution

  • Your query with $and looks correct. The problem might be that your meters to radian conversion might be wrong

    According to the docs dividing by 3963.2 is for converting miles to radians. Similarly the docs also state that to covert km to radians you have to divide by 6378.1. So to convert meters to radians have to divide by 6378100

    db.collection.aggregate([
      {
        $match: {
          $and: [
            {
              "point.coordinates": {
                $geoWithin: {
                  $geometry: {
                    type: "Polygon",
                    coordinates: [[
                      [21.654939727403415, 50.10333291665514],
                      [21.656736672596585, 50.10333291665514],
                      [21.656736672596585, 50.10453288334485],
                      [21.654939727403415, 50.10453288334485],
                      [21.654939727403415, 50.10333291665514]
                    ]]
                  }
                }
              }
            },
            {
              "point.coordinates": {
                $not: {
                  $geoWithin: {
                    $centerSphere: [
                      [21.6558382, 50.1039329],
                      0.0000031357300763550272 // 0.02/6378.1 for km to radians
                    ]
                  }
                }
              }
            }
          ]
        }
      }
    ])
    

    https://mongoplayground.net/p/Uv5JOz8vfcb