2014-02-13 71 views
0

当我最需要它时,堆栈帮了我大忙,我要再次测试我的运气。这是场景。目前我有以下型号:关于如何使用Django和PostgreSQL构建位置模型的建议(postGIS)

class Location(models.Model): 
    name = models.CharField(max_length=200, blank=True) 
    address = models.CharField(max_length=255, blank=True) 
    city = models.CharField(max_length=140, null=True, blank=True) 
    province_state = models.CharField(max_length = 140, null=True, blank=True) 
    country = models.CharField(max_length=2, null=True, blank=True) 
    postal_code = models.CharField(max_length=32, null=True, blank=True) 
    foursquare_id = models.CharField(max_length=100, blank=True, unique=True) 
    lat = models.DecimalField(max_digits=18, decimal_places=15, null=True, blank=True) 
    lon = models.DecimalField(max_digits=18, decimal_places=15, null=True, blank=True) 

看起来挺直挺的吧?现在我所做的是返回位于用户当前位置100公里范围内的所有位置。每个学位大约100公里。例如,在10度到11度的纬度之间,距离100公里。与经度相同。 1度约为100公里。这是我的看法WhatsNearBy:

@csrf_exempt 
def WhatsNearBy(request): 
    if request.META.has_key('HTTP_AUTHORIZATION') and request.method == 'GET': 
     authmeth, auth = request.META['HTTP_AUTHORIZATION'].split(' ', 1) 
     if authmeth.lower() == 'basic': 
      auth = auth.strip().decode('base64') 
      username, password = auth.split(':', 1) 
      authuser = authenticate(username=username, password=password) 
      if authuser: 
       if authuser.is_active: 
       client_lat = int(request.GET.get('lat')) 
       client_lon = int(request.GET.get('lon')) 

       queryset = Location.objects.filter(__lat__gte = (client_lat - 1), 
           lat__lte = (client_lat + 1), 
           lon__gte = (client_lon - 1), 
           lon__lte = (client_lon + 1)) 
       return queryset 

以上的查询集返回所有大约100公里的位置。这工作很好,而且非常稳固。但是,我担心的是随着数据库变大,过滤迟早会变慢。

我听说过有关postGIS,但我不确定它是否会比我现在做的更有效率。我需要将位置模型迁移到postGIS吗?这一切如何工作?一旦我做到了,我能够在一定距离内找到所有的位置?

期待看到您的解决方案!

回答

1

我最近处理了一个类似的问题。我发现PostGIS和其他空间解决方案对于在近似半径内查找所有点是过度杀伤性的。

我结束了在数据库中使用SAS距离算法。使用正方形过滤后,我使用raw命令让数据库为我编写数字。 Postgres和除SQLite以外的大多数其他数据库都支持trig函数,因此您可以过滤数据库的计算距离。这是以英里为单位的公式,但您可以更改常数。

Dist = 3949.99 * arcos(sin(Y1) * sin(Y2) + cos(Y1) * cos(Y2) * cos(X1 - X2)); 

http://support.sas.com/kb/3/973.html

编辑:要展开,我被查询半径内的所有美国邮政编码(〜44K)。事实证明,我可以在几分之一秒内查询500英里内的所有邮政编码,这些邮政编码对于我的目的来说是可接受的。地理空间库允许您更快速地找到复杂多边形内的所有点,但我不指望您会看到应用程序显着的性能改进。

+0

感谢您的回复! – noahandthewhale