0

I have a function which queries my database to find nearby users. However, my database stores the longitude and latitude of users, and to find the distance from the user, I need to call a function (distance) to check which users to return in the query. Is there a way to do what I have in the code (call my local distance function inside my querystring?)

exports.getNearby = function (longitude, latitude) {
var long1 = longitude;
var lat1 = latitude;
return new Promise(((resolve, reject) => {
    const queryString = `SELECT ${userModel.userId}
     FROM ${userModel.collectionName} where SELECT distance(${userLocationModel.latitude},
     ${userLocationModel.longitude}, ${lat1}, ${long1}) < 4`;
    db.query(queryString, (err, res) => {
        if (err) {
            logger.log('error', ` getUser - ${userIdArr} - ${err}`);
            reject(err);
        } else {
            resolve(res.rows[0]);
        }
    });
}));
};

function distance(lat1, lon1, lat2, lon2) {             //returns in km
  return 12742 * asin(sqrt(0.5 - cos((lat2 - lat1) * 0.01745329252)/2 
    + cos(lat1 * 0.01745329252) * cos(lat2 * 0.01745329252) * 
    (1 - cos((lon2 - lon1) * 0.01745329252)) / 2));
}

Function written in Postgres (as suggested by @LaurenzAlbe)

CREATE FUNCTION distance(
lat1 double precision,
lng1 double precision,
lat2 double precision,
lng2 double precision
) RETURNS double precision AS 
'SELECT 12742
     * asin(
         |/ (
             0.5 - cos(
                 (lat2 - lat1) * 0.01745329252
             )/2 
             + cos(lat1 * 0.01745329252)
             * cos(lat2 * 0.01745329252)
             * (1 - cos(
                 (lon2 - lon1) * 0.01745329252
             )) / 2
         )
    )'
LANGUAGE sql IMMUTABLE;

1 Answer 1

1

If you want to use the function in an SQL statement, you have to define it inside the database using CREATE FUNCTION.

For a function like that, I'd choose LANGUAGE sql.

Have you considered using the PostGIS extension if you want to do geographical data processing inside the database? It offers all imaginable functions out of the box.

Here is how your function could look as SQL function:

CREATE FUNCTION distance(
    lat1 double precision,
    lng1 double precision,
    lat2 double precision,
    lng2 double precision
) RETURNS double precision AS 
'SELECT 12742
         * asin(
             |/ (
                 0.5 - cos(
                     (lat2 - lat1) * 0.01745329252
                 )/2 
                 + cos(lat1 * 0.01745329252)
                 * cos(lat2 * 0.01745329252)
                 * (1 - cos(
                     (lon2 - lon1) * 0.01745329252
                 )) / 2
             )
        )'
    LANGUAGE sql IMMUTABLE;
Sign up to request clarification or add additional context in comments.

11 Comments

Would the edit I added be the correct code syntax to create a postgres function?
I have added my rendition.
I forgot the IMMUTABLE.
what does that keyword do?
It tells PostgreSQL's query optimizer that the function will always return the same result for the same arguments. It also makes the function usable in indexes. In your case, the function will get inlined for efficiency.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.