Получить метрическое расстояние между двумя точками с помощью запроса PostgreSQL/PostGIS

У меня есть вопрос об использовании postgreSQL/postGIS.

Я хотел бы отобразить маркеры на карте (хранящиеся в базе данных), которые находятся на некотором расстоянии от пользователя (координаты, заданные в запросе).

Тип поля маркеров - POINT (я храню lat/long). Положение пользователя определяется API Google Map.

Вот актуальный запрос:

SELECT * FROM geo_points WHERE ST_distance(ST_SetSRID(geo_points.coords::geometry,4326),ST_GeomFromEWKT('SRID=4326;POINT(45.0653944 4.859764599999996)')) > 65

Я знаю (после некоторых исследований в Интернете), что функция ST_distance дает мне расстояние в градусах между маркерами и положением пользователя, и что я проверяю расстояние в км.

Я думаю, что я должен использовать функцию ST_tranform для преобразования точек в метрических координатах.

Итак, мои вопросы: - что такое SRID для Франции - как я могу сделать это динамически для всего мира в соответствии с позицией пользователя?

Я также знаю, что функция ST_within существует и может это сделать. Но я предвижу тот факт, что позже мне может понадобиться расстояние.

Любая помощь будет принята с благодарностью

ps: возможно, есть решения в другом посте, но все ответы, которые я нашел во время моих исследований, не соответствовали моим потребностям.

1 ответ

Решение

Во-первых, обратите внимание на порядок координат, используемый PostGIS, он должен быть long/lat. В настоящее время вы ищете в Сомали. Сменив координаты, вы будете искать во Франции.

Вы можете использовать геодезический расчет с типом географии или использовать геодезические функции, такие как ST_Distance_Spheroid. С типом geography вы можете использовать ST_DWithin для более высокой производительности.

Вот geo_points 65 м или менее от достопримечательности Франции (не Сомали):

SELECT * FROM geo_points
WHERE ST_Distance_Spheroid(
    ST_Transform(geo_points.coords::geometry, 4326),
    ST_SetSRID(ST_MakePoint(4.859764599999996, 45.0653944), 4326),
    'SPHEROID["WGS 84",6378137,298.257223563]') < 65.0;

Однако он будет очень медленным, поскольку ему нужно найти расстояние до каждой точки geo_points, поэтому делайте это только в том случае, если вам не нужна производительность и у вас меньше нескольких тысяч точек.

Если вы измените и преобразуете geo_points.coords хранить лон / лат (WGS84) как geography тип:

SELECT * FROM geo_points
WHERE ST_DWithin(
    geo_points::geography,
    ST_SetSRID(ST_MakePoint(4.859764599999996, 45.0653944), 4326)::geography,
    65.0);
Другие вопросы по тегам