Postgresql 如何准确地存储地理位置数据、在半径范围内过滤并计算距离?

Postgresql 如何准确地存储地理位置数据、在半径范围内过滤并计算距离?,postgresql,postgis,Postgresql,Postgis,我用以下内容编写新位置: ST_设置网格(ST_生成点(:经度,:纬度),4326) 它们被保存在“profile”下。位置: SRID=4326;点(-75.1234 35.1234) 我尝试在米范围内过滤:radius中的配置文件,其中:ownLocation是由一组数字组成的位置字符串: ST_DWithin(“profile.location,:ownLocation::geometry,:radius) 然后,当我返回结果并使用以下公式计算它们的距离时: ST_距离( ST_变换(“p

我用以下内容编写新位置:

ST_设置网格(ST_生成点(:经度,:纬度),4326)

它们被保存在
“profile”下。位置

SRID=4326;点(-75.1234 35.1234)

我尝试在米范围内过滤
:radius
中的配置文件,其中
:ownLocation
是由一组数字组成的位置字符串:

ST_DWithin(“profile.location,:ownLocation::geometry,:radius)

然后,当我返回结果并使用以下公式计算它们的距离时:
ST_距离(
ST_变换(“profile”。location::geometry,3857::int),ST_变换(:ownLocation::geometry,3857::int)
)作为距离

把米的距离换算成英里,我的结果有点不对劲。假设我将最大半径设置为10英里以内——我返回的距离似乎在0-23英里之间(预计为0-10英里)

我想知道我在这里哪里出错了,我有一种感觉,这可能与投影有关,或者我使用的函数不正确


解决方案后更新:存储为
4326
,显示距离为
3857

存储为
4326

ST_设置网格(ST_生成点(:经度,:纬度),4326)

使用
geography
类型进行过滤,以便它可以接受过滤半径作为用户将通过的米:

ST_DWithin(“profile.location::geography,:ownLocation::geography,:radiusInMeters)

显示从
4326
3857
米的距离,并进行校正():


EPSG 4326的单位为度,而EPSG 3857的单位为米

ST_DWithin(“profile.location,:ownLocation::geometry,:radius”)将度作为半径,而不是米或英里


转换“轮廓”。位置和:ownLocation::几何体到3857应该可以工作

EPSG 4326的单位为度,而EPSG 3857的单位为米

ST_DWithin(“profile.location,:ownLocation::geometry,:radius”)将度作为半径,而不是米或英里


转换“轮廓”。位置和:ownLocation::几何体到3857应该可以工作

3857不适合计算距离,因为当你离开赤道时,它会引入重要的失真

相反,您可以使用
ST_Distance
使用
geography
数据类型:

ST_Distance("profile".location::geography,:ownLocation::geography) as distance

关于st_dwithin
,它使用投影单位,即度,而不是米。您也可以在此处使用
地理数据类型。

3857不适合计算距离,因为它会在您离开赤道时引入重要的失真

相反,您可以使用
ST_Distance
使用
geography
数据类型:

ST_Distance("profile".location::geography,:ownLocation::geography) as distance

关于st_dwithin
,它使用投影单位,即度,而不是米。您也可以在此处使用
geography
数据类型。

除了使用仪表的
ST_DWithin
之外,还有更好的替代方案吗?我正在尝试过滤“获取距离您自己位置10英里内的配置文件”,其中用户将以英里/公里的半径通过,因此我宁愿使用米而不是度(除非转换起来很简单?)。将度转换为米是错误的(纬度与经度的地面长度不同). 您可以使用另一个保留距离的投影(如UTM),也可以依赖地理数据类型,因为距离将以米为单位返回。我明白您的意思。因此,只要您输入
geography
类型:
boolean stu DWithin(几何图形g1、几何图形g2、双精度距离/u srid)
boolean stu DWithin(地理图形gg1、地理图形gg2、双精度距离/u m)相比,stu DWithin与米是兼容的
所以我应该在任何地方都使用
地理
类型,但您能否澄清我是应该将我的积分保存为
4326
还是应该切换到其他内容?听起来我不应该将它们另存为
3857
,因为这对距离不好?它们都有各自的优点和局限性。3857代表性非常常见。您必须评估您的需求以及在各种预测/地理位置中与您的每个需求相关的“成本”,然后找到最佳的需求。检查这个好的,谢谢!根据你的提示,我做了一些更新(如原始问题所示),似乎给了我预期的结果。提到
(有趣的事实:这就是为什么我们在EPSG:4326中存储数据,但在EPSG:3857中显示它!)
并显示一个更正,以给出我满意的结果。除了使用仪表的
ST_DWithin
之外,还有更好的替代方案吗?我正在尝试过滤“获取距离您自己位置10英里内的配置文件”,其中用户将以英里/公里的半径通过,因此我宁愿使用米而不是度(除非转换起来很简单?)。将度转换为米是错误的(纬度与经度的地面长度不同). 您可以使用另一个保留距离的投影(如UTM),也可以依赖地理数据类型,因为距离将以米为单位返回。我明白您的意思。因此,只要您输入
geography
类型:
boolean stu DWithin(几何图形g1、几何图形g2、双精度距离/u srid)
boolean stu DWithin(地理图形gg1、地理图形gg2、双精度距离/u m)相比,stu DWithin与米是兼容的
所以我应该在任何地方都使用
地理
类型,但您能否澄清我是应该将我的积分保存为
4326
还是应该切换到其他内容?听起来我不应该将它们另存为
3857
,因为这对距离不好?它们都有各自的优点和局限性。3857代表性非常常见。你不会的