You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vapor4中如何使用PostGIS实现按经纬度距离过滤Pers模型

解决方案

前置准备

  • 首先确保你的PostgreSQL数据库已经安装并启用PostGIS扩展,登录数据库后执行以下SQL即可:
    CREATE EXTENSION IF NOT EXISTS postgis;
  • 你原有控制器里的逻辑存在冗余:不需要从请求中解码[Pers]数组,我们直接将距离计算逻辑下沉到数据库层执行,避免全量拉取数据再内存过滤的性能问题。

核心查询实现

Fluent支持传入自定义SQL片段作为过滤条件,我们可以直接调用PostGIS的距离计算函数实现需求,修改后的控制器代码如下:

import Foundation
import Vapor
import Fluent
import FluentPostgresDriver

final class InformationController{
    func temp(_ req:Request) throws -> EventLoopFuture<[Pers]> {
        // 解码用户传入的位置参数
        let userLocation = try req.content.decode(Pers.UserLocation.self)
        // 指定搜索半径,单位:米
        let searchRadius: Double = 100
        
        // 直接用PostGIS函数在数据库层过滤
        return Pers.query(on: req.db)
            .filter(.sql(raw: """
                ST_DistanceSphere(
                    ST_MakePoint(經度, 緯度),
                    ST_MakePoint($1, $2)
                ) < $3
                """,
                bindings: [
                    userLocation.lonitude,
                    userLocation.latitude,
                    searchRadius
                ]
            ))
            .all()
    }
}

注意:PostGIS的ST_MakePoint函数参数顺序是先经度后纬度,不要写反,否则计算出来的距离会完全错误。

性能优化建议

如果你的people表数据量较大,可以给经纬度字段加GIST空间索引大幅提升查询速度,执行以下SQL创建索引:

CREATE INDEX idx_people_location ON people USING GIST (ST_MakePoint(經度, 緯度));

进阶方案(可选)

如果后续有大量地理位置相关查询需求,可以引入FluentPostGIS库,将Pers模型的经纬度合并为单个PostGIS Point类型字段,后续查询写法会更简洁,也不需要手动构造点对象。

内容的提问来源于stack exchange,提问作者蔡濡安

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:54:05