2012-07-04 3 views
3

У меня есть модель с PointField для координат местоположения. У меня есть функция MySQL, которая вычисляет расстояние между двумя точками, которое называется dist. Я использую extra() «select» для вычисления расстояния для каждого возвращаемого объекта в наборе запросов. Я также использую extra() «где» для фильтрации тех объектов, которые находятся в определенном диапазоне. Как этоСчетчик запросов Django с дополнительным выбором

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

Это прекрасно работает для получения и чтения результатов, за исключением того, когда я пытаюсь подсчета результирующего я получаю ошибку, что «расстояние» не является полем. После изучения немного дальше, кажется, что счет игнорирует «выбор» из дополнительного и просто использует «где». В то время как полный 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? или вы можете использовать другую СУБД? – jperelli

ответ

0

Вы можете использовать raw query, если вы не планируете использовать какую-либо другую систему баз данных.

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

Кроме того, если вам нужна дополнительная поддержка ГИС, вы должны оценить PostgreSQL + PostGIS (Если вам не нравится изобретать колесо, вы не должны сделать свой собственный DIST функцию)

Джанго предлагает поддержку ГИС через GeoDjango. Там у вас есть функции, такие как distance. Вы должны проверить поддержку here

Для того, чтобы использовать GeoDjango вам необходимо добавить поле на YOUT модели, чтобы сказать им, чтобы использовать GeoManager, тогда вы можете начать делать geoqueries, и вы не должны иметь никаких проблем с count.

с MySQL вы Cando что-то вроде этого, используя 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() 

вы можете увидеть лучшие примеры here и ссылки here

+0

Спасибо за ваш ответ. Я не могу использовать PostgreSQL, потому что мы ограничены Amazon RDS, который запускает MySQL. Я мог бы использовать raw sql. Но как мне сделать COUNT(), в результате чего результат dist() является условием? Мне нужно учитывать только результаты, расстояние которых находится в определенном диапазоне. –

+0

У MySQL есть базовая поддержка ГИС, вы пробовали geodjango? вы можете сделать это: 'YoourModel.objects.filter (your_geo_field__distance_lt = (a_geom, D (m = 5))). count()' – jperelli

+0

Также не пытайтесь использовать псевдоним для функции dist select dist. В необработанном запросе вы должны фильтровать с помощью функции (dist) с параметрами в предложении where, а затем count (*) в предложении select. – jperelli

Смежные вопросы