Подтвердить что ты не робот

Как я могу запросить ближайшую запись в заданных координатах (широта и долгота типа строки)?

Я использую GeoDjango с PostGIS. Тогда у меня возникают проблемы с тем, как получить ближайшую запись из данных координат из таблицы postgres db.

4b9b3361

Ответ 1

Это ответ с использованием GeoDjango с PostGIS

Координаты точек должны быть объектом GEOSGeometry. Чтобы использовать его

from django.contrib.gis.geos import GEOSGeometry
point = GEOSGeometry('POINT(5 23)')

Тогда представьте, что у вас есть модель "Ресторан" и координаты точки. Итак, для ближайшего ресторана просто используйте:

Restaurants.objects.distance(point).order_by('distance')[0] 

Ответ 2

В следующей версии PostGIS 2.0 появилась функция KNN gist, чтобы получить функции ближайшего соседа. Например:

SELECT ST_Distance(geom, 'SRID=26910;POINT(34.5 -23.2)'::geometry) AS d
FROM mypoints
ORDER BY geom <-> 'SRID=26910;POINT(34.5 -23.2)'::geometry LIMIT 1;

Эта функция находится в версии SVN, и вы можете ее протестировать/использовать сейчас.

Ответ 3

Я должен согласиться с ответом delawen, но сам по себе st_distance будет очень медленным. Чтобы ускорить работу, вам нужно использовать индексы GIST (обратите внимание на большую часть функции PostGIS, включая st_distance. НЕ используйте индексы: рекомендация по индексированию postgis).

Итак, сначала вы создадите буфер вокруг точки, а затем проверите его ограничивающий прямоугольник, используя "& &" (это использует встроенный индекс GIST, поэтому он будет работать намного лучше), а затем вы проверите расстояние "st_distance".

Например, чтобы получить ближайший "ресторан" из заданного местоположения (например, X = 1, Y = 1), вы должны написать:

select *,st_distance(the_geom_col,st_geomfromtext('POINT(1 1)',27700)) as distance 
from restaurants where st_buffer(st_geomfromtext('POINT(1 1)',27700),100) 
&& "the_geom_col"

Это будет очень быстро по сравнению с "st_distance", но результаты могут содержать рестораны, которые находятся на расстоянии более 100 метров от данного места (например, когда геометрия поддерживается в линейном или многоугольном форматах).

Чтобы получить более точные результаты, рестораны, которые находятся точно в диапазоне 100 метров, вы добавьте, следуя приведенному выше запросу:

and st_distance(the_geom_col,st_geomfromtext('POINTFROMTEXT(1 1)',27700)) <= 100

Это будет по-прежнему более эффективным и быстрым, чем использование st_distance самостоятельно. Поскольку база данных будет запускать st_distance только для записей, которые соответствуют первым критериям.

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

  • Отфильтруйте как можно больше ложных результатов, используя специальные операторы (см. специальные операции в официальные документы postgis.
  • Затем напишите фактическую функцию проверки пространственных отношений.
  • Всегда указывайте индекс GIST в столбце "geometry".
  • Добавьте ограничивающие поля к вашим "геометриям", используя st_addbbox.
  • Регулярно переиндексации и вакуумирования/анализа ваших таблиц.

Примечание. Размер буфера или фактическое расстояние должен быть в системе проецирования, которую вы используете, т.е. если вы используете EPSG: 4326 (Lat/Long), то вы даете эти расстояния в градусах. Например 1 метр в реальном мире = 0,00000899 градусов.. и 100 метров = делать математику:)

Ответ 4

У меня нет опыта работы с GeoDjango, но на PostgreSQL/PostGIS у вас есть функция st_distance (..). Итак, вы можете заказать свои результаты st_distance(geom_column, your_coordinates) asc и посмотреть, какие ближайшие строки.

Если у вас есть простые координаты (без геометрии postgis), вы можете преобразовать ваши координаты в точку с помощью функции geometryFromText.

Это то, что вы искали? Если нет, попробуйте быть более явным.

Ответ 5

Пользователи PostgreSQL/PostGIS должны использовать оператор " ↔ " в предложении ORDER BY, чтобы получить "K ближайших соседей" (KNN), как сказано в Mike T в этот ответ.

Чтобы получить преимущества от улучшения производительности KNN-GiST в GeoDjango, вы можете написать следующее:

from django.contrib.gis.db.models.functions import GeomValue
from django.contrib.gis.geos import Point
from django.db.models.expressions import CombinedExpression, F

knn = 10
longitude = -96.876369
latitude = 29.905320
pnt = Point(longitude, latitude, srid=4326)
order_by_expression = CombinedExpression(F('geom'), '<->', GeomValue(pnt))
nearest_neighbors = Neighbor.objects.order_by(order_by_expression)[:knn]

Ответ 6

Использование PostGIS и GeoDjango для поиска ближайшего соседа

Рассмотрим эту модель:

from django.contrib.gis.geos import Point
from django.contrib.gis.db import models

    class Store(models.Model):
        name = models.CharField(max_length=100)
        location = models.PointField(geography=True, srid=4326)
        longitude = models.FloatField()
        latitude = models.FloatField()
        objects = models.GeoManager()
    def save(self, **kwargs):
        self.location = Point(self.longitude, self.latitude)
        super(Store, self).save(**kwargs)

В представлении найдите все точки интереса в радиусе 100 миль от заданной долготы/широты:

from django.contrib.gis.geos import Point
from django.contrib.gis.measure import D

point = Point(lng, lat)
points = Store.objects.filter(
    location__distance_lte=(point, D(mi=100))
).distance(point).order_by('distance')

Показать результаты в шаблоне:

<ul>
    {% for point in points %}
    <li>{{ point.name }} is {{ point.distance.mi|floatformat }} miles away</li>
    {% endfor %}
</ul>