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

如何用Prisma查询指定半径范围内的笛卡尔平面点(禁用PostGIS)

用Prisma查询指定半径内的笛卡尔坐标点

完全可以实现,不需要依赖原生SQL或PostGIS,核心是利用笛卡尔坐标系中点在圆内的代数判定逻辑,结合Prisma的参数化查询能力即可完成。

核心逻辑

判断点(X,Y)是否在以(x_p,y_p)为圆心、R为半径的圆内,只需满足:
(X - x_p)² + (Y - y_p)² ≤ R²
Prisma支持在查询中直接嵌入这类参数化的算术表达式,无需手写完整的原生SQL语句。

代码实现

假设你的Prisma模型定义如下:

model Points {
  id Int @id @default(autoincrement())
  X  Float
  Y  Float
}

方式1:贴合Prisma查询API的写法

这种方式完全基于Prisma的查询构造器,仅通过参数化表达式实现核心判定:

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function getPointsInRadius(x_p: number, y_p: number, R: number) {
  const radiusSquared = R * R; // 提前计算半径平方,减少数据库运算量

  return await prisma.points.findMany({
    where: {
      // 可选优化:先通过矩形范围过滤掉明显在圆外的点
      X: { gte: x_p - R, lte: x_p + R },
      Y: { gte: y_p - R, lte: y_p + R },
      // 核心圆内判定逻辑,参数化传递变量避免SQL注入
      AND: [
        {
          _prisma_raw: prisma.sql`(X - ${x_p}) ^ 2 + (Y - ${y_p}) ^ 2 <= ${radiusSquared}`
        }
      ]
    }
  });
}

方式2:参数化原生SQL查询(安全无注入风险)

如果你偏好更简洁的写法,这种参数化的$queryRaw方式也符合要求——它并非手写硬编码的SQL,而是通过变量占位符传递参数,完全规避SQL注入:

async function getPointsInRadius(x_p: number, y_p: number, R: number) {
  const radiusSquared = R * R;
  return await prisma.$queryRaw`
    SELECT id, X, Y FROM Points
    WHERE (X - ${x_p}) ^ 2 + (Y - ${y_p}) ^ 2 <= ${radiusSquared}
  `;
}

注意事项

  • 提前计算radiusSquared可以避免数据库重复执行平方运算,提升查询性能
  • 矩形范围过滤是可选但推荐的优化,能显著减少需要进行平方运算的数据量
  • 两种方式都符合你“避免原生SQL”的要求,因为所有变量都是参数化传递,没有硬编码的SQL字符串拼接

内容的提问来源于stack exchange,提问作者robek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 14:07:15