Django 查找距离点x英里以内的对象

Django 查找距离点x英里以内的对象,django,geodjango,Django,Geodjango,我正在努力获取用户位置10英里范围内的所有事件。我的模型看起来像这样: class User(models.Model): location = models.PointField() ... class Event(models.Model): location = models.PointField() ... 在我的测试中,当我检查用户和事件之间的距离时,我得到值11.5122663513: from geopy.distance import vin

我正在努力获取用户位置10英里范围内的所有事件。我的模型看起来像这样:

class User(models.Model):
    location = models.PointField()
    ...


class Event(models.Model):
    location = models.PointField()
    ...
在我的测试中,当我检查用户和事件之间的距离时,我得到值
11.5122663513

from geopy.distance import vincenty

print vincenty(request.user.location, event.location).miles # 11.5122663513
然而,当我查询用户位置10英里范围内的所有事件时,会返回该事件:

Event.objects.filter(location__distance_lte=(request.user.location, D(mi=10))).count() # 1
只有当我将半径降低到小于4英里时,过滤器才会生效:

Event.objects.filter(location__distance_lte=(request.user.location, D(mi=3))).count() # 0
我几乎完全遵循了这个原则,所以我认为我的问题不在于我的问题


造成这种差异的原因是什么?

这在很大程度上取决于您使用的数据库类型

因为笛卡尔数学比地理空间数学快得多,所以查询可能会将坐标视为在平面上而不是球体上

他们这样解释:

大多数人都熟悉使用纬度和经度来表示 参考地球表面的一个位置。但是,纬度和 经度是角度,不是距离。换句话说,当 平面上两点之间的最短路径是一条直线, 曲面上两点之间的最短路径(例如 地球)是一个大圆的弧。因此,需要进行额外的计算 需要以平面单位获取距离(例如,公里和 英里)。使用地理坐标系可能会引入 开发人员稍后会遇到复杂的问题。例如,Spatialite就是这样做的 不具备在两个传感器之间执行距离计算的能力 使用地理坐标系的几何图形,例如构建 查询以查找存储为的县边界5英里内的所有点 WGS84

地球表面的一部分可以投射到二维平面上, 或者笛卡尔,平面。投影坐标系尤其重要 适用于特定地区的应用,例如,如果您知道 您的数据库将只覆盖堪萨斯州北部的几何图形,然后您可以 考虑使用特定于该区域的投影系统。此外 投影坐标系以笛卡尔单位定义(例如 米或英尺),简化了距离计算

此外,这可能会受到数据库选择的影响。如果您使用的是Postgres/PostGIS,文档中有以下注释:

在PostGIS中,ST_Distance_Sphere不限制几何体类型 地理距离查询使用。然而,这些 查询可能需要很长时间,因为必须使用较大的圆距离 为查询中的每一行动态计算。这是因为 无法使用传统几何体字段上的空间索引

<>在WGS84距离查询上有更好的性能,考虑使用 而不是数据库中的地理列,因为它们能够 在距离查询中使用它们的空间索引。你可以告诉我去哪里 通过在字段中设置geography=True来使用geography列 定义

您可以通过打印原始SQL来检查这一点:

qs = Event.objects.filter(location__distance_lte=(request.user.location, D(mi=10))
print qs.query
根据您的数据库类型和计划存储的数据量,您有两个选项:

  • 在python中再次过滤这些点
  • 尝试设置
    geography=True
  • 设置明确的
  • 取一个具有给定半径的点,然后使用
    contains
  • 使用不同的数据库类型

如果共享原始查询,将更容易了解发生了什么。

我最终使用了缓冲区将一个点变为一个圆选项。对于其他选择该选项的人,请确保。