2012-07-04 97 views
3

我有一個PointField的位置座標模型。我有一個MySQL函數,用於計算兩個點之間的距離,稱爲dist。我使用extra()「select」來計算查詢集中每個返回對象的距離。我還使用extra()「where」來過濾特定範圍內的那些對象。像這樣Django queryset count with extra select

query = queryset.extra(
    select={ 
     "distance":"dist(geomfromtext('%s'),geomfromtext('%s'))"%(loc1, loc2) 
    }, 
    where=["1 having `distance` <= %s"%(km)] 
) #simplified example 

這工作正常獲取和閱讀的結果,除了當我嘗試計數結果集我得到「距離」是不是現場錯誤。在進一步探索之後,似乎count忽略了來自extra的「select」,而只是使用「where」。雖然完整的SQL查詢看起來是這樣的:

SELECT (dist(geomfromtext('POINT (-4.6858300000000003 36.5154300000000021)'),geomfromtext('POINT (-4.8858300000000003 36.5154300000000021)'))) AS `distance`, `testmodel`.`id`, `testmodel`.`name`, `testmodel`.`email`, (...) FROM `testmodel` WHERE 1 having `distance` <= 50.0 

計數查詢更短且沒有DIST選擇部分:

SELECT COUNT(`testmodel`.`id`) FROM `testmodel` WHERE 1 having `distance` <= 50.0 

從邏輯上講,MySQL的給出了一個錯誤,因爲「距離」未定義。有沒有辦法告訴Django它必須包含額外的計數選擇?

感謝您的任何想法!

+0

你需要堅持與MySQL參考CANDO這樣的事情?或者你可以使用另一個RDBMS? – jperelli

回答

0

如果您不打算使用任何其他數據庫系統,則可以使用raw query

params = {'point1':wktpoint1, 'point2':wktpoint2} 
    query = """ 
     SELECT 
      dist(%(point1)s, %(point2)s) 
     FROM 
      testmodel 
    ;""" 
    query_set = self.raw(query, params) 

另外,如果你需要更多的GIS支持,你應該評估的PostgreSQL + PostGIS(如果你不喜歡推倒重來,你不應該讓自己的測距功能)

Django還提供GIS支持通過GeoDjango。你有這樣的功能,如distance。您應該檢查支持here

爲了使用GeoDjango內置您需要添加一個字段上YOUT模型,告訴他們使用GeoManager,然後你就可以開始做geoqueries,你應該沒有問題count

與MySQL你使用GeoDjango內置

### models.py 
from django.contrib.gis.db import models 
class YourModel(models.Model): 
    your_geo_field=models.PolygonField() 
    #your_geo_field=models.PointField() 
    #your_geo_field=models.GeometryField() 
    objects = models.GeoManager() 

### your code 
from django.contrib.gis.geos import * 
from django.contrib.gis.measure import D 
a_geom=fromstr('POINT(-96.876369 29.905320)', srid=4326) 
distance=5 
YoourModel.objects.filter(your_geo_field__distance_lt=(a_geom, D(m=distance))).count() 

你可以看到更好的例子herehere

+0

感謝您的回答。我無法使用PostgreSQL,因爲我們僅限於運行MySQL的Amazon RDS。我可以使用原始的SQL。但我怎麼做COUNT()把dist()結果作爲條件?我只需要計算結果,該距離在一定範圍內。 –

+0

MySQL有基本的GIS支持,你有沒有試過geodjango?你可以這樣做:'YoourModel.objects.filter(your_geo_field__distance_lt =(a_geom,D(m = 5)))。count()' – jperelli

+0

另外,不要使用距離選擇dist函數的別名。 在原始查詢中,您應該使用where子句中的參數使用函數(dist)進行篩選,然後在select子句中計數(*)。 – jperelli