尽管数据存在,但 GraphQL 查询上的日期字段返回为 null

问题描述 投票:0回答:2

我在将一些数据从 PostgreSQL 数据库传输到服务时遇到问题。

设置方式是这样的:

Service1 向 Service2 发送 GraphQL 请求以请求数据。 Service2 将此数据存储在 PostgreSQL 数据库中,并从中获取信息。

数据被建模为带有 TypeORM 和 GraphQL 装饰器的实体。我遇到问题的确切字段是:

   @Column({
        nullable: true,
        type: 'timestamp'
    })
    @Field(() => GraphQLISODateTime, {nullable: true})
    executed_on: Date

当数据从数据库到达service2时,它存在,所有字段都存在,并且日期字段及其值存在。

从数据库获取时的字段:

"executed_on": "2019-10-27T23:00:00.000Z"

从Service1获取时的字段:

"executed_on": null

当它发送到 service1 时,我可以 console.log 数据并看到那里的字段。我假设由于 GraphQL 以 JSON 格式发送数据,因此日期字段变成了字符串。现在,当此数据从 service1 传输到其他地方时,所有

executed_on
字段值都变为空。我不知道为什么会出现这种情况。难道是因为现在它是一个字符串,所以它没有被解析到日期字段中?

我发现的一个解决方法是循环遍历数组中的每个对象,并简单地从当前字符串值创建一个新的 Date 对象,但这不是我想要做的事情,因为当我获取时,这个过程也在其他服务中发生来自外部 REST API 的数据,所以我猜这会是一个糟糕的设计?我对此很陌生。

如有任何帮助,我们将不胜感激。

node.js graphql typeorm
2个回答
1
投票

我面临着类似的问题,我相信这是由于 DateTime 类型的 GraphQl 节点模块中的序列化错误造成的。

这就是失败的地方:

// node_modules/graphql/execution/execute.js:
completeLeafValue(returnType, result) {
  // this returns null even though a correct "value" is being passed in
  var serializedResult = returnType.serialize(result);
  ...

因为它的序列化器由于“value instanceof Date”而失败并简单地返回 null:

serialize(value) {
  return value instanceof Date ? value.toISOString() : null;
}

出于某种原因, type=Date 被强制转换为“DateTime” 为什么我还没有弄清楚,但在我看来它应该抛出一个错误而不是只返回 null。

正如您已经说过的:唯一的解决方法/修复方法是为对象树中的每个日期字段创建一个新的 Date(...) 对象。

或者分叉原始存储库并将此代码添加到“completeLeafValue”方法中:

//node_modules/graphql/execution/execute.js:
completeLeafValue(returnType, result) {
  var serializedResult = returnType.serialize(result);
  if(completeLeafValue==="DateTime") {
    result = new Date(result);
    //new Date(...) does not throw and only returns null when it fails
    //so we have to check for null
    if(result === null) { 
      throw new Error(`Cannot cast ${result} to Date object`);
    }
  }
  ...(rest or original fn)

0
投票

为了确保正确处理时间戳,您可以添加时间戳的自定义类型解析器。

在 PostgreSQL 中,数据类型是通过类型 OID(对象标识符)来标识的,1114 是时间戳数据类型的 OID 类型

const { types } = require('pg');
types.setTypeParser(1114, stringValue => new Date(stringValue + 'Z'));
© www.soinside.com 2019 - 2024. All rights reserved.