3

By sending latitude longitude of current Location, I would like to find the nearest airport in my collection.

I've used geodist for finding the distance between two latitute/longitude coordinates.

Question: Is it possible to make a query after getting all collection of airport to check whether the current location is available within a specific distance?

E.g. When minimum current distance to an item of the collections is within 100km, then I would like to show this item as result.

This My Query...

return Airport
    .find(_.pick(params, _.keys(Airport.schema.paths)))
    .populate(_.keys(_.groupBy(_.reject(
        strapi.models.airport.associations, {autoPopulate: false}), 'alias')).join(' '));

This My Route...

{
    "method": "GET",
    "path": "/airport/:latitude/:longitude/",
    "handler": "Airport.findOne",
    "config": {
        "policies": []
     }
},

This my Controller...

findOne: async (ctx) => {
    return strapi.services.airport.fetch(ctx.params);
},
sɐunıɔןɐqɐp
  • 3,332
  • 15
  • 36
  • 40

2 Answers2

4

Maybe you have solved but if can help someone my approach has been:

  /**
   * Promise to fetch all near shops.
   *
   * @return {Promise}
   */

  fetchAllNear: async (params) => {
    const convertedParams = strapi.utils.models.convertParams('shops', params)

    let data = {}
    let populatedShopsActive = {}

    data = await new Promise((resolve, reject) => {
      Shops.aggregate([
        {
          '$geoNear': {
            'near': { type: 'Point', coordinates: [ parseFloat(params._lon), parseFloat(params._lat) ] },
            'limit': 100,
            'maxDistance': parseFloat(params._distance),
            'distanceField': 'distance',
            'distanceMultiplier': 0.001,
            'spherical': true
          }
        }
      ]).exec(async (err, shops) => {
        await Shops.populate(shops, {
          path: _.keys(_.groupBy(_.reject(strapi.models.shops.associations, {autoPopulate: false}), 'alias')).join(' '),
          populate: {
            path: 'shop image',
            populate: {
              path: 'image'
            }
          }
        }, async (err, populatedShops) => {
          if (err) {
            reject(err)
          } else {
            if (params._todayOffers === 'true') {
              populatedShopsActive = await _.forEach(populatedShops, async (shop) => {
                await _.remove(shop.offers, (offer) => {
                  return !(_moment(offer.end_date).isSame(new Date(), 'day'))
                })
              })
            } else {
              populatedShopsActive = await _.forEach(populatedShops, async (shop) => {
                await _.remove(shop.offers, (offer) => {
                  return !(_moment(new Date()).isBetween(offer.start_date, offer.end_date, null, '[]'))
                })
              })
            }

            resolve(populatedShopsActive)
          }
        })
      })
    })

    return data
  },
lag
  • 53
  • 1
  • 10
  • Do you mind explaining more on your sample? Did you use any library like geodist or postgis? Or just plain SQL there? – Yen Sheng May 08 '19 at 02:07
  • Nothing library. I have used mongo geospatial query. Simple and fast. [documentation about it](https://docs.mongodb.com/manual/geospatial-queries/) – lag May 08 '19 at 09:12
  • @lag is this a custom controller you have created for a new API endpoint to run this geospatial query? I'm currently trying to achieve the same. Also what's the format you have saved these location points in Strapi - since there is not 'GeoLocation' field. – RamithDR Dec 10 '20 at 09:02
  • 2
    @RamithDR 'fetchAllNear' is a method of my shop controller that run when custom API has invoked. As you can see strapi not support geolocation field but you can use json field named location example: **location: { type: 'Point', coordinates: [_lat, _lon]}** so inside a custom method you can easy retrieve it. Check your version of mongodb because this snippet is write one year ago so something might have changed. [This ref](https://docs.mongodb.com/manual/release-notes/4.2-compatibility/#remove-support-for-the-geonear-command) can be useful if you want try to new mongodb version. – lag Dec 11 '20 at 01:15
  • Using this soluton, do the standard Strapi model functions still work? e.g. filter params in URL like "Cost_gte=20". ... or do you have to re-build the entire controller from scratch? – Kalnode May 26 '21 at 18:19
1

I got solution on my case :

let entities;
    entities = await strapi.services.projects.find({
      geo_location: {
        $near: {
          $geometry: {
            type: "Point",
            coordinates: [21.1702401, 72.83106070000001],
          },
          $minDistance: 0,
          $maxDistance: 5000,
        },
      },
    });
    return entities;
Akshay I
  • 3,675
  • 1
  • 34
  • 57