Search code examples
node.jsmongodbaggregation-frameworkpipeline

How to use $geoNear on array of embedded documents?


My document structure is like the following:

{ agency_key : '',
  route_id: '',
  direction_id: '',
  stops: [ 
           {stop_id:15, 
            stop_lat: '',
            stop_lon: '',
            loc: [-83.118972, 42, 121567]
            },
            {...
            }
          ]
}

I want to find the stops which are close to a given (lat,lon) pair within a given distance from every document in the collection. I created 2d indexes. I tried $unwind, then $geoNear but it says $geoNear can only be at the first stage of the pipeline. I tried this:

db.tm_stops.aggregate([ 
... { 
...  $geoNear: { near: {coordinates: [-82.958841, 42.370114] },      distanceField: "stops.calculated", query: { agency_key: "DDOT"}, 
... includeLocs: "stops.loc" }
... }
... ])

I tried the following:

 db.tm_stops.find({stops:{$near:[-82.958841, 42.370114], $maxDistance: 1 } } )

It throws this error:

error: {
    "$err" : "Unable to execute query: error processing query: ns=gtfs.tm_stops limit=0 skip=0\nTree: GEONEAR  field=stops maxdist=1 isNearSphere=0\nSort: {}\nProj: {}\n planner returned error: unable to find index for $geoNear query",
    "code" : 17007

What should be my mongo query? I will need to execute this from a Node.js application but I want to see some result in Mongo shell first. Thanks in advance.


Solution

  • I finally made the query work. I am answering my own question for future reference. Since I am using 2d index and not 2dsphere, I didn't have to use coordinates in near operator. This query works:

    db.tm_stops.aggregate([ 
     { 
      $geoNear: 
        { near: [-82.958841, 42.370114] ,     
         distanceField: "stops.calculated", 
         query: { agency_key: "DDOT"}, 
         includeLocs: "stops.loc" }
         }
       ])
    

    But I discovered, in the returned document, i can only see the calculated distance and the (lon, lat) pair used to calculate the distance. I can't really returned the whole embedded document which is used for the calculation.

    If I find a way to return the whole embedded document, I'll update my answer.