Sitemap

How to search nearby places using Strapi without broking the query system

2 min readJun 17, 2021
Press enter or click to view image in full size

Hello folks, if you are there, it means that you have been looking for a way to make geo query using strapi unsuccessfully, in this article I will show you how to tacle it.

This article suppose you are able to run a Strapi project without any issue , so in this article we will be focused on how to handle a request like this http://localhost:1337/items?_latitude=3.888360&_longitude=11.51290&_distance=500 , basically we are trying to fetch all items 500 meters around the point (3.888360,11.51290).

To do so,let say we have created a model named “item”, you will need to save latitude and longitude of each items, so this is how my file /api/item/models/item.settings.json will look like :

{    "kind": "collectionType",    "collectionName": "items",    "info": {         "name": "Places",         "description": ""    },    "options": {        "increments": true,        "timestamps": true,       "draftAndPublish": true    },    "pluginOptions": {        "i18n": {            "localized": true        }    },    "attributes": {        "latitude": {            "type": "float",            "pluginOptions": {            "i18n": {                "localized": true            }        }    },        "longitude": {            "type": "float",            "pluginOptions": {                "i18n": {                    "localized": true                }           }        }    }}

Now open you file /api/item/service/item.js

Press enter or click to view image in full size

const { convertRestQueryParams, buildQuery } = require(‘strapi-utils’);

Override the find method:

module.exports = {async find(params, populate, { transacting } = {}) {const latitude=params._latitude;const longitude=params._longitude;const distance=params.distance;const isGeoQuery = latitude && longitude && distance;delete params._latitude;delete params._longitude;delete params.distance;const distanceInMilesSql=`ST_distance_sphere( point(latitude, longitude), point(${latitude}, ${longitude})) as distance`;const knex = strapi.connections.default;const filters = convertRestQueryParams(params);const model = strapi.models.item;const query = buildQuery({ model, filters });return model.query(qb=>{if(isGeoQuery){console.log('Is geo query');qb.column(knex.raw(distanceInMilesSql));qb.having('distance','<',distance);qb.orderBy('distance');}query(qb);}).fetchAll({withRelated: populate,transacting,publicationState: filters.publicationState,}).then(results => results.toJSON());}

That is all, now you can query items around a specified point without broking the existing filter feature.

--

--

loic NGOU
loic NGOU

Written by loic NGOU

I am a self starter web and mobile developer, who like to play with flutter, laravel, strapijs and vue.

No responses yet