jon.m
11/14/2021, 5:45 PMScott P
11/14/2021, 6:33 PMgeolib (for JS).
If you've got a set of data in Postgres and want to search for e.g. nearest points from the user location, there's a few things to setup. I've done this for things like bus stops, since users will usually want to know where bus stops are within an area as opposed to remembering a street name.
1. Ensure that each row has a latitude and longitude property and that all rows have valid data for these columns.
2. Ensure that you've enabled (or installed, if self-hosting) the postgis extensions
3. Update your table so that it has a geometry column of type extensions.geometry
4. Update every row in the table to create the geometry data (in this example, the table is called `some_table`:
sql
UPDATE public.some_table SET geometry = extensions.ST_SetSRID(extensions.ST_MakePoint(longitude, latitude), 4326);Scott P
11/14/2021, 6:33 PMsql
CREATE OR REPLACE FUNCTION public.search_locations_by_distance(
in_latitude real,
in_longitude real,
max_distance_in_meters integer,
result_limit integer DEFAULT 20)
RETURNS TABLE(
atco_code text,
naptan text,
common_name text,
short_common_name text,
landmark text,
street text,
crossing text,
bearing text,
longitude real,
latitude real,
geographic_area text,
distance double precision
)
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
BEGIN RETURN QUERY
SELECT *
FROM public.some_table as stops,
extensions.ST_Distancesphere(
stops.geometry,
extensions.ST_MakePoint(in_longitude, in_latitude)
) as distance
WHERE extensions.ST_Distancesphere(
stops.geometry,
extensions.ST_MakePoint(in_longitude, in_latitude)
) < LEAST (max_distance_in_meters, 5000)
ORDER BY distance ASC
LIMIT LEAST (result_limit, 100);
END;
$BODY$;
In that example, it allows me to specify a latitude, a longitude, a maximum distance, and a result limit. It also enforces a maximum distance of 5000 meters and 100 results using the LEAST function.
After you've gone through that setup, you're able to call it with the JS library like this:
js
SupabaseClient.rpc("search_locations_by_distance", {
in_latitude: <user latitude>,
in_longitude: <user longitude>,
max_distance_in_meters: 800,
})
result_limit will default to 20 if not specified.Scott P
11/14/2021, 6:42 PMjon.m
11/14/2021, 7:10 PMScott P
11/14/2021, 7:14 PMjon.m
11/14/2021, 7:17 PMjon.m
11/21/2021, 11:50 PMburggraf
11/22/2021, 3:31 PMburggraf
11/22/2021, 3:34 PMWHERE
earth_box(ll_to_earth(${lat}, ${lng}), ${radius}) @> ll_to_earth("Latitude", "Longitude")
AND earth_distance(ll_to_earth(${lat}, ${lng}),
ll_to_earth("Latitude", "Longitude")) < ${radius}
ORDER BY distance LIMIT 200burggraf
11/22/2021, 3:36 PMlat and lng, the fields in the database are named Latitude and Longitude, and you also pass it radius which is in meters, which would be the max search radius.burggraf
11/22/2021, 3:36 PMEARTHDISTANCE extension!