我的项目中使用了GeoDjango和PostGIS。现在我遇到了问题,需要从我的PostgreSQL数据库表中获取给定坐标的最近记录。
我的项目中使用了GeoDjango和PostGIS。现在我遇到了问题,需要从我的PostgreSQL数据库表中获取给定坐标的最近记录。
这是使用GeoDjango和PostGIS的答案。
点坐标必须是一个GEOSGeometry对象。要使用它,请
from django.contrib.gis.geos import GEOSGeometry
point = GEOSGeometry('POINT(5 23)')
假设您有一个“餐厅”模型和点的坐标。那么,要找到最近的餐厅,只需使用:
Restaurants.objects.distance(point).order_by('distance')[0]
[0]
是因为结果有序的第一条记录吗? -distance
是什么?它是模型几何类型的字段名吗? - erosPostGIS 2.0及更高版本可以使用KNN最近邻搜索来获取最近的质心。例如:
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;
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
注意:缓冲区大小或实际距离必须在你正在使用的投影系统中,即如果你正在使用 EPSG: 4326(纬度/经度),那么你必须以度数给出这些距离。例如,现实世界中的 1 米 = 0.00000899 度...而 100 米 = 做一下数学 :)
PostgreSQL/PostGIS用户应在ORDER BY子句中使用“<->”运算符来获取“K最近邻居”(KNN),正如Mike T在此答案中所说。
为了从GeoDjango中的KNN-GiST性能提升中获益,您可以编写以下内容:
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]
我没有使用过GeoDjango,但在PostgreSQL/PostGIS中有st_distance(..)函数。因此,您可以按照 st_distance(geom_column, your_coordinates) asc
的顺序对结果进行排序,并查看最近的行。
如果您只有普通坐标(没有postgis几何图形),则可以使用geometryFromText函数将其转换为点。
这是您想要的吗?如果不是,请尽量详细说明。
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>