Calculating distance between a gps location and postgis geography value using a function?

烈酒焚心 提交于 2021-02-19 07:44:08

问题


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.

  1. 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.

  2. 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$;
  1. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!