在 GeoDjango 中使用 distance() 时出现数据库错误

发布于 2024-11-19 22:54:14 字数 2645 浏览 1 评论 0原文

给定以下(简化的)模型:

from django.contrib.gis.db import models

class City(models.Model):
    center = models.PointField(spatial_index=True, null=True)
    objects = models.GeoManager()

class Place(models.Model):
    city = models.ForeignKey(City, null=True)
    lat = models.FloatField(null=True)
    lng = models.FloatField(null=True)
    objects = models.GeoManager()

暂时忘记了 Place 中的经纬度应该移动到 PointField() ,我试图查看所有的地点 code> 并找到最近的城市。目前,我正在做:

from django.contrib.gis.geos import Point

places = Property.objects.filter(lat__isnull=False, lng__isnull=False)
for place in places:
    point = Point(place.lng, place.lat, srid=4326) # setting srid just to be safe
    closest_city = City.objects.distance(point).order_by('distance')[0]

这会导致以下错误:

DatabaseError: geometry_distance_spheroid: Operation on two GEOMETRIES with different SRIDs

假设 SRID 没有默认为 4326,我在上面的代码中包含 srid=4326 并验证所有城市都有 City.center 的 SRID 为 4326:

In [6]: [c['center'].srid for c in City.objects.all().values('center')]
Out[6]: [4326, 4326, 4326, ...]

对于可能导致此问题的原因有什么想法吗?

更新:

SQL 查询的创建方式似乎存在一些问题。抛出错误后,查看 sql 显示:

In [9]: from django.db import connection
In [10]: print connection.queries[-1]['sql']
SELECT (ST_distance_sphere("model_city"."center", 
    ST_GeomFromEWKB(E'\\001\\001...\\267C@'::bytea))) AS "distance", 
    "model_city"."id", "model_city"."name", "listing_city"."center" 
    FROM "model_city" ORDER BY "model_city"."name" ASC LIMIT 21

看起来 django 正在将 distance()point 参数转换为扩展众所周知的二进制文件。 如果我随后将 ST_GeomFromEWKB 更改为 ST_GeomFromText 一切正常。示例:

# SELECT (ST_distance_sphere("listing_city"."center",
          ST_GeomFromText('POINT(-118 38)',4326))) AS "distance", 
          "model_city"."name", "model_city"."center" FROM "model_city" 
          ORDER BY "listing_city"."name" ASC LIMIT 5;

     distance     |    name     |                       center                       
------------------+-------------+----------------------------------------------------
 3124059.73265751 | Akron       | 0101000020E6100000795DBF60376154C01CB62DCA6C8A4440
  3742978.5514446 | Albany      | 0101000020E6100000130CE71A667052C038876BB587534540
 1063596.35270877 | Albuquerque | 0101000020E6100000CC0D863AACA95AC036E7E099D08A4140

我在文档中找不到任何说明 如何使用的内容GeoQuerySet.distance() 转换为 SQL。我当然可以在查询中使用原始 SQL 来让事情正常工作,但更愿意将所有内容都很好地保留在 Django 框架中。

Given the following (simplified) models:

from django.contrib.gis.db import models

class City(models.Model):
    center = models.PointField(spatial_index=True, null=True)
    objects = models.GeoManager()

class Place(models.Model):
    city = models.ForeignKey(City, null=True)
    lat = models.FloatField(null=True)
    lng = models.FloatField(null=True)
    objects = models.GeoManager()

Forgetting for the moment that the lat/lng in Place should be moved to a PointField(), I am trying to look through all of the Places and find the closest city. Currently, I am doing:

from django.contrib.gis.geos import Point

places = Property.objects.filter(lat__isnull=False, lng__isnull=False)
for place in places:
    point = Point(place.lng, place.lat, srid=4326) # setting srid just to be safe
    closest_city = City.objects.distance(point).order_by('distance')[0]

This results in the following error:

DatabaseError: geometry_distance_spheroid: Operation on two GEOMETRIES with different SRIDs

Assuming that the SRIDs were not defaulting to 4326, I included srid=4326 in the above code and verified that all of the cities have City.center has an SRID of 4326:

In [6]: [c['center'].srid for c in City.objects.all().values('center')]
Out[6]: [4326, 4326, 4326, ...]

Any ideas on what could be causing this?

UPDATE:

There seems to be something in how the sql query is created that causes a problem. After the error is thrown, looking at the sql shows:

In [9]: from django.db import connection
In [10]: print connection.queries[-1]['sql']
SELECT (ST_distance_sphere("model_city"."center", 
    ST_GeomFromEWKB(E'\\001\\001...\\267C@'::bytea))) AS "distance", 
    "model_city"."id", "model_city"."name", "listing_city"."center" 
    FROM "model_city" ORDER BY "model_city"."name" ASC LIMIT 21

It looks like django is turning the point argument of distance() into Extended Well-Known Binary. If I then change ST_GeomFromEWKB to ST_GeomFromText everything works fine. Example:

# SELECT (ST_distance_sphere("listing_city"."center",
          ST_GeomFromText('POINT(-118 38)',4326))) AS "distance", 
          "model_city"."name", "model_city"."center" FROM "model_city" 
          ORDER BY "listing_city"."name" ASC LIMIT 5;

     distance     |    name     |                       center                       
------------------+-------------+----------------------------------------------------
 3124059.73265751 | Akron       | 0101000020E6100000795DBF60376154C01CB62DCA6C8A4440
  3742978.5514446 | Albany      | 0101000020E6100000130CE71A667052C038876BB587534540
 1063596.35270877 | Albuquerque | 0101000020E6100000CC0D863AACA95AC036E7E099D08A4140

I can't find anything in the documentation that speaks to how GeoQuerySet.distance() translates into SQL. I can certainly use raw SQL in the query to get things to work, but would prefer to keep everything nicely in the Django framework.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

聊慰 2024-11-26 22:54:14

我认为这个错误:“对具有不同 SRID 的两个几何图形进行操作”

数据库上的“geometry_columns”表在要处理的表名之间设置了不同的 srid

***** 您应该自己更改它
在此处输入图像描述

i think this error : "Operation on two GEOMETRIES with different SRIDs"

"geometry_columns" table on your database is set different srid between your table name to process

***** you should change it yourself
enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文