Home > Blockchain >  Mongo aggregation : Sort by distance at the end of pipeline
Mongo aggregation : Sort by distance at the end of pipeline

Time:06-10

I'm making an aggregation and making $lookup to get a collection where the location is .

The problem is : I cant do a $geoNear after the first stage of the pipeline. So I tried $nearSphere at the end of pipeline but it didn't work.

Any other way ? If I could get the distance I could sort the array after the aggregation.

The only solution I found, is : after the aggregation, I calculate the distance from the same point for each document and sort them but I'm not sure sure it is the most optimized !

Here is the aggregation I tried:

MyCollection.aggregate([
  {
    $match: {
      job: 'professor'
    }
  },
  {
    $lookup: {
      from: "otherCollection",
      localField: "_id",
      foreignField: "_id",
      as: "otherCollection"
    }
  },
  {
    $unwind: {
      path: "otherCollection",
      "preserveNullAndEmptyArrays": true
    }
  },
  {
    $addFields: {
      location: '$otherCollection.location'
    }
  },
  {
    $nearSphere: {
      $geometry: {
        type: "Point",
        coordinates: [lng, lat] // Those avriables are passed in arguments in the function before
      },
      $maxDistance: radius * 1000,
      // I tried to add a $key field to get $otherCollection._id but it doesn't worked
    }

  }
], function(err, data) {
  if (err) errorCbk(err)

  successCbk(data)
});

Thanks.

CodePudding user response:

You can use $sort and make any calculation you want on it https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort/

CodePudding user response:

You could "invert" the query by first using "$geoNear" in otherCollection and then "$lookup" into MyCollection.

Something like this.

db.otherCollection.aggregate([
  {
    "$geoNear": {
      "near": {
        "type": "Point",
        "coordinates": [ -46.0, -68.0 ]
      },
      "maxDistance": 2000000,
      "distanceField": "dist.calculated"
    }
  },
  {
    "$lookup": {
      "from": "MyCollection",
      "localField": "_id",
      "foreignField": "_id",
      "pipeline": [
        { "$match": { "job": "professor" } }
      ],
      "as": "nearProfs"
    }
  },
  {
    "$match": {
      "$expr": {
        "$gt": [ { "$size": "$nearProfs" }, 0 ]
      }
    }
  }
])

Try it with fake data on mongoplayground.net.

  • Related