数据流混合整数&长类型

时间:2015-11-10 03:14:16

标签: google-cloud-platform google-cloud-dataflow

在我的数据流管道中,我将字段impressions_raw设置为Long对象中的com.google.api.services.bigquery.model.TableRow

enter image description here

在我的管道中,我再次阅读TableRow。但是,我取代Long而不是Integer

enter image description here

但是,如果我明确将值设置为大于Long的{​​{1}}值,例如30亿,那么我会返回Integer.MAX_VALUE

enter image description here enter image description here

似乎Dataflow SDK正在进行某种类型的检查优化。

因此,如果不进行丑陋的类型检查,应该如何以编程方式处理此问题? (也许我错过了一些明显的东西)

1 个答案:

答案 0 :(得分:3)

感谢您的报告。不幸的是,这个问题是使用TableRow的基础。我们强烈推荐下面的解决方案1:在您的管道中尽快转换离TableRow

杰克逊在TableRowJsonCoder内对您存储这些值的TableRow对象进行序列化和反序列化。杰克逊完全按照你所描述的行为 - 也就是说,对于这个班级来说:

class MyClass {
    Object v;
}

它会将v = Long.valueOf(<number>) {v: 30}{v: 3000000000}的实例序列化。但是,在反序列化时,它将使用表示答案所需的位数来确定对象的类型。请参阅this SO post

我想到了两种可能的解决方案,强烈建议使用解决方案1:

  1. 不要将TableRow用作中间值。换句话说,尽快转换为POJO。这种混淆发生的关键原因是TableRow基本上是Map<String, Object>而杰克逊(或其他程序员)不知道你想要Long回来。使用POJO,类型将是明确的。

    关闭TableRow的另一个好处是找到一个有效的编码器,比如AvroCoder。因为TableRow被编码并从JSON解码,所以编码既冗长又缓慢 - 混乱TableRow将是CPU和I / O密集型。我希望您使用Avro编码的POJO可以看到比使用TableRow个对象时更好的性能。

    有关示例,请参阅LaneInfo in TrafficMaxLaneFlow

  2. 编写可以处理两者的代码:

    long numberToLong(@Nonnull Number n) {
        return n.longValue();
    }
    long x = numberToLong((Number) row.get("field"));
    
    Long numberToLong(@Nonnull Number n) {
        if (n instanceof Long) {
            // avoid a copy
            return n;
        }
        return Long.valueOf(n.longValue());
    }
    Long x = numberToLong((Number) row.get("field"));
    

    如果n可能是null,您可能需要对第二种变体进行额外检查。