3 votes

Trouver des lieux à proximité de plusieurs sites

J'essaie d'exécuter une requête qui trouvera des lieux à une distance donnée de n'importe quel lieu donné. Il s'agit d'un résultat de recherche où les utilisateurs peuvent sélectionner plusieurs lieux à visiter.

Mon approche actuelle consiste à utiliser ST_ClosestPoint et transmet un tableau de ST_Point généré en PHP. Ensuite, je passe cette chaîne dans ST_Collect .

$points = $locations->map(function ($location) {
    return sprintf('ST_Point(%s, %s)', $location->longitude, $location->latitude);
})->implode(', ');

SELECT *
FROM listing_locations
WHERE ST_DWithin(
    coordinate,
    ST_ClosestPoint(coordinate, ST_Collect(Array[%s]),
    1000, 
FALSE)

Cependant, cela ne fonctionne pas car cela ressemble à ST_ClosestPoint n'aime pas ces arguments contradictoires :

SQLSTATE[42883]: Undefined function: 7 ERROR:  function st_closestpoint(geometry, geography) does not exist

J'ai un gist(coordinate::geography) index sur listing_locations qui semble être utile à utiliser.

Qu'est-ce qui m'échappe ? Existe-t-il une meilleure façon de procéder ou s'agit-il d'une mauvaise approche ? Devrais-je effectuer la requête à chaque fois avec un emplacement différent ?

3voto

Jim Jones Points 2350

Pour simplifier les choses, mettez le ST_Collect dans une sous-requête ou un CTE, et dans la requête extérieure, utilisez ST_DWithin avec le MultiPoint nouvellement créé, la colonne coordinate et une distance donnée, par exemple

WITH j (points) AS (
  SELECT 
   ST_Collect( 
    (ST_SetSRID(ST_MakePoint(-81.70361, 28.62167), 4326)),
    (ST_SetSRID(ST_MakePoint(-81.70365, 28.62169), 4326))
   )::geography
)
SELECT *, ST_Distance(j.points,coordinate) AS distance
FROM listing_locations
JOIN j ON ST_DWithin(j.points,coordinate,100,false);

Ou le mettre dans une jointure spatiale (imho moins lisible)

SELECT *, ST_Distance(j.points,coordinate) AS distance
FROM listing_locations
JOIN (SELECT
       ST_Collect( 
        (ST_SetSRID(ST_MakePoint(-81.70361, 28.62167), 4326)),
        (ST_SetSRID(ST_MakePoint(-81.70365, 28.62169), 4326))
       )::geography) j (points)
       ON ST_DWithin(j.points,coordinate,100,false);

Démonstration : db<>fiddle

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X