MongoDB.live, free & fully virtual. June 9th - 10th. Register Now MongoDB.live, free & fully virtual. June 9th - 10th. Register Now

Matching points from one collection with polygons from another

I’m trying to match points in one collection with regions stored in another collection.
Here are examples of documents.

Points:

{ 
  "_id" : ObjectId("5e36d904618c0ea59f1eb04f"), 
  "gps" : { "lat" : 50.073288, "lon" : 14.43979 },  
  "timeAdded" : ISODate("2020-02-02T15:13:22.096Z") 
}

Regions:

{
  "_id" : ObjectId("5e49a469afae4a11c4ff3cf7"), 
  "type" : "Feature", 
  "geometry" : { 
    "type" : "Polygon", 
    "coordinates" : [[ 
        [ 14.609644294937652, 50.02081908813608 ],
        [ 14.609640493282695, 50.02078482460302 ],
        [ 14.609603249828798, 50.020776412254065 ],
        [ 14.609548954187744, 50.02072977072492 ],
        ... 
        [ 14.609433408712134, 50.0208718692152 ],
        [ 14.609644294937652, 50.02081908813608 ]
      ]] 
  }, 
  "properties" : {  
    "Name" : "Region 1" 
  } 
}

And the query I’m trying to construct is something like this:

db.points.aggregate([
  {$project: {
    coordinates: ["$gps.lon", "$gps.lat"]
  }}, 
  {$lookup: {
    from: "regions", pipeline: [
      {$match: {
        coordinates: {
          $geoWithin: {
            $geometry: {
              type: "Polygon", 
              coordinates: "$geometry.coordinates"
            }
          }
        }
      }}
    ], 
    as: "district"
  }}
])

I’m getting an error:

assert: command failed: {

    "ok" : 0,
    "errmsg" : "Polygon coordinates must be an array",
    "code" : 2,
    "codeName" : "BadValue"

} : aggregate failed

I’ve noticed the structure of $geoWithin document is same as structure of one I have for each region. So I tried such query:

db.points.aggregate([
  {$project: {
    coordinates: ["$gps.lon", "$gps.lat"]
  }}, 
  {$lookup: {
    from: "regions", pipeline: [
      {$match: {
        coordinates: {
          $geoWithin: "$geometry.coordinates"
        }
      }}
    ], 
    as: "district"
  }}
])

The error was same.

I looked up for geoqueries but surprisingly all found mentions had static region document instead of one taken from a collection. So I’m wondering - is it ever possible to map points with regions having that both document collections aren’t static and taken from DB?

Hi @Mychajlo_Chodorev, welcome!

In order to use expressive $lookup, the $match value in the pipeline requires to be an expression. Currently it’s not possible to use $geoWithin as an expression, there’s an open ticket for this SERVER-34766. Please feel free to watch/up-vote the ticket to receive update on it.

One way to achieve what you’ve described is to use a client application to query from Points collection then programmatically build a geo query for Regions collection .

Regards,
Wan.