使用 Fluent 4 查询 PostgreSQL 数据库位置

PostgreSQL DB location query with Fluent 4

我有一个存储具有纬度和经度的项目的应用程序,我想创建一个查询来过滤项目并根据它们与给定 lat/lon 对的距离对它们进行分页。

网上看了很多解法,在fluent的限制下似乎不太可行

您最好的办法是根据给定的纬度 (lat) 和经度 (lng) 计算 angular 距离 (ang),然后select 将包含圆形的正方形区域。然后使用毕达哥拉斯过滤那些位于要求距离内的:

let ang2 = pow(ang, 2)
Point.query(on: req.db)
    .filter(\.$lng >= lng - ang).filter(\.$lng <= lng + ang)
    .filter(\.$lng >= lat - ang).filter(\.$lat <= lat + ang).all().flatMap { points in
        let closePoints = points.filter { pow([=10=].lat - lat, 2) * pow([=10=].lng - lng, 2) <= ang2) }
        // continue processing
    }
}

编辑:根据 OP 的披露,他想对结果进行分页!

捕获最后一组点的 id 值,然后对此进行过滤。类似于:

let ang2 = pow(ang, 2)
Point.query(on: req.db)
    .filter(\.$lng >= lng - ang).filter(\.$lng <= lng + ang)
    .filter(\.$lng >= lat - ang).filter(\.$lat <= lat + ang).all().flatMap { points in
        return points.filter { pow([=11=].lat - lat, 2) * pow([=11=].lng - lng, 2) <= ang2) }.map { [=11=].id }
    }.flatMap { ids in
        Point.query(on: req.db).filter(\.$id ~~ ids).paginate().flatMap { points in
             // continue processing
        }
    }
}

您需要将 PostGIS 用于任何类型的 Geometric/Geographic 查询。幸运的是,有一个包! https://github.com/brokenhandsio/fluent-postgis

您可以filterGeograghyWithin()在一定距离内找到物品。请注意,地理查询更适合此类转换(并且更准确),因为它们考虑了地球的曲率。

缺点是您需要将 lat/lon 列转换为原生 PostGIS 类型的 GeographicPoint2D,但考虑到 PostGIS 是此类工作的实际标准,它是值得的无论如何