使用 Java 将嵌套记录写入 BigQuery

Posted

技术标签:

【中文标题】使用 Java 将嵌套记录写入 BigQuery【英文标题】:Write nested record to BigQuery using Java 【发布时间】:2021-04-21 09:30:31 【问题描述】:

我想使用 Apache Beam 将一些嵌套数据写入 BigQuery,并想知道我为 BigQuery 表创建的架构是否正确。这是我的数据在 XML 中的样子:

<ID>5<ID>
<Addresses>
    <Address>
        <Street>Lincoln St.</Street>
        <ZipCode>03483</ZipCode>
    </Address>
</Addresses>

这就是我创建 BigQuery 架构以反映上述数据的方式:

[
    "name": "ID",
    "type": "STRING"
  ,
  
    "name": "Addresses",
    "type": "RECORD",
    "mode": "REPEATED",
    "fields": [
      
        "name": "Address",
        "type": "RECORD",
        "mode": "REPEATED",
        "fields": [
          
            "name": "Street",
            "type": "STRING"
          ,
          
            "name": "ZipCode",
            "type": "STRING"
          
        ]
      
    ]
  ]

这就是我解析上述结构以在 Java 中创建 BigQuery TableRow 的方式。

List<Address> addresses = getAddresses;

if (!addresses.isEmpty()) 
    List<TableCell> repeatedRecordInstanceList = new ArrayList<>();

    for (Address address : addresses) 
        List<TableCell> childObject = new ArrayList<>();

        if (address.getStreet() != null) 
            childObject.add(new TableCell().set("Street", address.getStreet()));
         else  childObject.add(new TableCell().set("Street", null)); 

        if (address.getZipCode() != null) 
            childObject.add(new TableCell().set("ZipCode", address.getZipCode()));
         else  childObject.add(new TableCell().set("ZipCode", null)); 
     
        repeatedRecordInstanceList.add(new TableCell().set("Address", childObject));
    
    tableRow.set("Addresses", repeatedRecordInstanceList);
 else 
        tableRow.set("Addresses", null);
  

但由于某种原因,这就是我的数据在 BigQuery 中的样子:

ID Addresses.Address.Street Addresses.Address.ZipCode
5 Lincoln St null
null 03483

似乎每个AddressStreetZipCode 都写成两次迭代。

我希望Street 和它各自的ZipCode 在同一行中没有任何空值。我怎样才能做到这一点?我会很感激一些帮助。谢谢。

【问题讨论】:

【参考方案1】:

据我了解您的代码,生成的对象在 JSON 格式中可能如下所示:


  "ID" : "5",
  "Addresses" : [
     "Address" : ["Street" : "abc", "ZipCode": "1564",
                   "Street" : "abd", "ZipCode": "1565"]
    ,
    "Address" : ["Street" : "abe", "ZipCode": "1566",
                  "Street" : "abf", "ZipCode": "1567",
                  "Street" : "abg", "ZipCode": "1568"]
    
  ]

我认为您不希望这样 - “地址”中可以有多个地址,然后“地址”中可以有多个“地址”。我认为“地址”不应该是modeREPEATED(这意味着它是一个数组)。这也意味着childObject 不应该是 ArrayList,因为如果你添加一个新元素,那么你就会在数组中添加一个新条目,不是吗?

【讨论】:

谢谢你,@Martin Weitzmann。我根据您的建议解决了这个问题,因为Address 总是会在StreetZipCode 中各有一个实例。

以上是关于使用 Java 将嵌套记录写入 BigQuery的主要内容,如果未能解决你的问题,请参考以下文章

使用 prisma,如何从嵌套写入中访问新创建的记录(先更新,然后在其中创建)

将记录器消息写入文件和文本区域,同时保持 Java 中的默认行为

将嵌套对象写入 Apollo 客户端缓存

如何使用 Apache Beam (Python) 将多个嵌套的 JSON 写入 BigQuery 表

JAVA序列化机制的深入研究

使用嵌套表将数据集写入xml