首页 > 解决方案 > 在 django orm 中使用 annotate() 在 MariaDB 服务器上运行 hasrsine 公式

问题描述

嗨,我试图根据我的模型在 MariaDB 上运行 Haversine 公式,
模型是

class MeteorologicalSite(models.Model):
    lat = models.DecimalField("Latitude", max_digits=17, decimal_places=15)
    lon = models.DecimalField("Longitude", max_digits=17, decimal_places=15)  
class Site(models.Model):
    lat = models.DecimalField("Latitude", max_digits=17, decimal_places=15)
    lon = models.DecimalField("Longitude", max_digits=17, decimal_places=15)

这是Haversine函数

def Haversine_formula(self, site):
    from django.db.models.functions import Cos, Sin, ASin, Sqrt, Radians
    lat1 = Radians(site.lat)
    lon1 = Radians(site.lon)
    lat2 = Radians(F("lat"))
    lon2 = Radians(F("lon"))
    r = 6372.8
    sql_haversine_formula = 2 * r * ASin( 
        Sqrt(

            Sin((lat1-lat2)/2)**2+
            Cos(lat1)*
            Cos(lat2)*
            Sin((lon1 - lon2)/2)**2
            )
        )
    MeteorologicalSite.objects.filter(radiation=True)\
        .annotate(mycolumn=sql_haversine_formula)

并且它没有运行它返回<django.db.models.query.QuerySet object at 0xffff57b99ca0>
我尝试直接将 lat 和 lon 用于 1 和 2 作为 Decimal 并且它仍然不起作用
所以我知道我的问题在于我使用 annotate 的方式或我使用 sql_haversine_formula
有没有人有想法为什么这不起作用?

对不起我的英语不好

标签: djangodjango-modelsmariadb

解决方案


MariaDB 支持ST_Distance_Sphere(这是 Haversine 公式)。(注意支持的版本,截至本文发表时它还算新)

使用Func你可以为 Django 包装它:

from django.db.models import Func

class Distance_Sphere(Func):
    function = 'ST_DISTANCE_SPHERE'

有了这个,您应该能够在查询中使用它。

信用:来自这个答案


推荐阅读