4

我正在使用pg-promise来访问我们的 postgres 数据库。我想调用一个foo(geom)接受几何数据类型(PostGIS)的存储过程。虽然我只有 lats/lngs 开始,所以我想使用 postGIS 转换它们。

这看起来像这样:

db.func('foo', 'ST_MakePoint(' + location.lat + ', ' + location.lng + ')')
  .then((result) => {
    console.log(bar);
  });

我现在收到一个错误,抱怨我的几何图形无效(转换没有发生)。我确信ST_MakePoint我所拥有的价值观是可行的。我猜它在数据库上执行时将其解释为字符串而不是函数调用。

我应该如何传递此参数以使其工作?

4

1 回答 1

6

我是pg-promise的作者;)

与使用pg-promise 的常规查询格式化不同,在其中您通过格式化变量指定格式化模板,在使用方法funcproc时会跳过它,因此它们隐含在值的类型中。

最优雅的解决方案是使用库支持的自定义类型格式,它允许您覆盖任何数据类型并提供自己的格式。

您可以像这样介绍自己的课程Point

function Point(lat, lng) {
    this.lat = +lat;
    this.lng = +lng;
    this.rawType = true; /* use as raw/unescaped value */
    this.toPostgres = p => {
        return 'ST_MakePoint(' + p.lat + ',' + p.lng + ')';
    };
}

然后您可以将其作为常规值传入:

const p = new Point(1, 2);

db.func('foo', [p]).then(...)

或者,您可以直接执行查询。不要高估方法func,它只是执行SELECT * FROM foo,所以你可以这样做:

const p = 'ST_MakePoint(' + lat + ',' + lng + ')';

db.any('SELECT * FROM foo($1:raw)', p).then(...)

:raw- 注入原始/未转义值。

PS 将来,与其猜测pg-promise执行什么,不如尝试pg-monitor ,或者至少处理eventquery

更新:2018 年 4 月 29 日

更新了自定义类型格式的语法以符合pg-promise支持的最新版本。

总结一个点的最短语法:

const point = (lat, lng) => ({
    toPostgres: ()=> pgp.as.format('ST_MakePoint($1, $2)', [lat, lng]),
    rawType: true
});

所以你可以简单地传递它:

db.func('foo', point(1, 2))
于 2017-01-25T17:31:32.660 回答