代码之家  ›  专栏  ›  技术社区  ›  MartinMlima

通过BigQuery库发送的Timestamp对象返回错误“此字段不是记录”

  •  1
  • MartinMlima  · 技术社区  · 6 年前

    当将日期字段作为对象发送到以时间戳形式键入的BigQuery表时,googlejavaapi库不会抛出异常,但不会抛出数据。检查“InsertAllResponse”响应类型会返回错误“This field is not a record”。

    Hashmap<String,Object> rowContent = new Hashmap<>();
    rowContent.put("Time", new Date());
    rowContent.put("Name", "Harry");
    

    然后

    BigQuery bq = BigQueryOptions.getDefaultInstance().getService();
    TableId tableId = TableId.of(datasetName, tableName);
    InsertAllRequest.Builder insertReqBuilder = InsertAllRequest.newBuilder(tableId);
    insertReqBuilder.addRow({some string}, row);
    InsertAllResponse response = bigquery.insertAll(insertReqBuilder.build());
    

    返回响应。hasErrors()true。

    还报告了 python here firebase here javascript here

    1 回复  |  直到 6 年前
        1
  •  3
  •   MartinMlima    4 年前

    似乎将日期作为对象发送会导致客户端API创建一个JSON记录,而不是单个字段(这也表明datetime类型没有显式映射,因此可能会引入时区问题)。

    相反,请以UTC格式发送日期/时间 自1970年起,即修改上述内容:

    Hashmap<String,Object> rowContent = new Hashmap<>();
    rowContent.put("Time", Math.floor(new Date().getTime()/1000));
    rowContent.put("Name", "Harry");
    

    (注:不知道如何处理毫秒,参见示例 BigQuery not dealing with timestamp in millisecond with partition column ,我会查出来再回来)

        2
  •  0
  •   DoomGoober    4 年前

    从Unix时代开始。这是相当愚蠢的,考虑到几乎所有人都使用毫秒,因为Unix Epoch和时间戳支持高达微秒的精度。如果你对秒没问题,用int作为秒。

    如果需要更高的精度,请将时间戳值转换为字符串。根据 this documentation 是:

    YYYY-[M]M-[D]D[( |T)[H]H:[M]M:[S]S[.DDDDDD]][time zone] 
    

    long milliseconds = 1610399564959L;
    LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(milliseconds), ZoneOffset.UTC);
    DateTimeFormatter timestampFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS");
    String timestampText = dateTime.format(timestampFormatter);
    rowContent.put("Time", timestampText);