如何在 Postgres/Postgis 中转换类型(并使用 sequelizejs)
Posted
技术标签:
【中文标题】如何在 Postgres/Postgis 中转换类型(并使用 sequelizejs)【英文标题】:How to cast a type in Postgres/Postgis (and using sequelizejs) 【发布时间】:2017-07-15 14:42:26 【问题描述】:我在 postgis 中有矢量瓦片。没有铸造类型的经验。 vector-tile-spec 支持以下类型:string、float、double、int64、uint64、sint64、bool。这意味着除了 Varchar、Text、CharArray、Float4、Float8、Int2、Int4、Int8、Bool 之外的所有 PostgreSQL 类型都必须转换为其中之一。
我的表中有两个字段是 DATES,即“带时区的时间戳”:createdAt 和 updatedAt。我想存储在受支持的类型中,我该怎么做?
我目前:
-
使用 sequelize(a.o. 定义 DATE 类型)创建架构
使用 ogr2ogr 进行批量导入(Postgis 在其中创建默认值
日期)
然后是 CRUD 和 sequelize。
但所有 3 个(或至少 2 个和 3 个)都需要最终成为受支持的类型。
我最好将 DATES 转换为哪种类型? 我该怎么做(使用 sequelize hooks?使用 Postgres?)?【问题讨论】:
【参考方案1】:我会将您的日期转换为 INTEGER
或 BIGINT
,具体取决于您需要使用的日期范围,并且只计算 Unix Time 的天数。
假设您只是转换为INTEGER
,您可以定义以下函数将dates
转换为自纪元日期 (1970-01-01 00:00:00
) 开始的天数:
CREATE FUNCTION days_from_reference_date(d date)
RETURNS INTEGER
AS
$$
SELECT
CAST(EXTRACT(epoch from d) / (60 * 60 * 24 /* seconds in a day */) AS INTEGER) ;
$$
LANGUAGE SQL
STRICT
IMMUTABLE ;
你可以在这样的场景中使用它:
SELECT
days_from_reference_date(d) AS transformed_date
FROM
dates
ORDER BY
transformed_date ;
可以通过以下方式进行反向转换:
CREATE FUNCTION date_from_days_from_reference_date(days integer)
RETURNS date
AS
$$
SELECT CAST(to_timestamp(cast(days as bigint) * 60 * 60 * 24) AS date);
$$
LANGUAGE SQL
STRICT
IMMUTABLE ;
您可以在 dbfiddle here
上查看一些示例参考资料:
Postgresql Date/Time Functions and Operators。寻找to_timestamp
和extract(epoch from ...)
。
警告:以 BC 日期偏移一天;如果您需要它们。它可能可以通过在反向转换函数中检查它们来解决。
【讨论】:
感谢您的回答。这很有帮助。您是否还可以建议如何实现它,因为所需的行为是创建一个时间戳,然后立即将其转换为数字(或文本)。 如果您需要处理timestamps
而不是dates
,请使用前面的函数,不要除以或乘以(24 * 60 * 60)。至于实现细节:这在很大程度上取决于您使用的 ETL 工具。我可能会将数据暂存在一些临时 PostgreSQL 表中,从中创建一些视图,将您的 timestamps
转换为 integer
或 bigint
并将它们导出到您的最终系统。我不知道sequelize.js
是如何工作的,所以我只能采用一般方法。以上是关于如何在 Postgres/Postgis 中转换类型(并使用 sequelizejs)的主要内容,如果未能解决你的问题,请参考以下文章