问题
I have lat and long values for a user. I have addresses of various locations saved in db. I want to find the nearest offers based on a radius value. I am using postgis.
Currently my location column is of type geography.
What is the format in which I should enter the data into "location" column geography type when I have only latitude and longitude? I cannot use postgis functions since I am using graphql to do data insert.
I have been tearing my hair apart trying to write a function for this purpose. This is what I came up with.Is there a better way to do this?
CREATE OR REPLACE FUNCTION public."getNearByOffers"(
lat double precision,
lon double precision,
radius integer)
RETURNS "Offers"
LANGUAGE 'sql'
COST 100
VOLATILE
AS $BODY$ SELECT O.*
FROM "public"."Offers" O
JOIN "public"."Address" A ON A.id = O."addressId"
WHERE
ST_DWithin(ST_MakePoint(lat, lon)::geography,
A.location::Geography, radius);$BODY$;
- When I run this function all in the query result columns are merged together. How can I split it to different columns in query result?
I would really appreciate any help in this matter!
回答1:
Hasura has built in support for PostGIS in their GraphQL schema. Since your field is already of type geography
, you don't need the function.
In Hasura you need to create the relationship between the offers
and address
tables, and the GraphQL query should be something like:
query nearby_offers($point: geography!) {
offers(where: {address: {location: {_st_d_within: {distance: 200000, from: $point}}}}) {
id
offer_fields
address {
location
}
}
}
Geography type in Hasura expects the value to be in GEOJSON
format. Here is how your variable $point
should look like:
{
"point": {
"type" : "Point",
"coordinates": [longitude, latitude]
}
}
The same type of variable (GEOJSON) is expected when inserting values (mutation).
回答2:
For GIS operations, you want the point data type. You can use a VIEW
to create a pseudo-table that contains the original columns plus the radii and/or points. You can't create an index on the view (if that matters), but you might be able to make one on the expression. I'm not equipped to try this at the moment but could revise it later if this doesn't answer your question.
Something like
CREATE VIEW offer_address AS (
SELECT o.*, ST_DWithin(ST_MakePoint(a.lat, a.lon), a.location) radius
FROM offers o JOIN address a ON a.id = o."addressId"
);
Then you insert into offers
and address
as usual and query, but not insert into, offer_address
.
P.S. GraphQL itself shouldn't prevent you from executing arbitrary SQL, but I'm not sure what your setup is exactly.
来源:https://stackoverflow.com/questions/62974333/calculating-distance-between-a-gps-location-and-postgis-geography-value-using-a