目的:
我们希望使用AWS Glue数据目录为S3存储桶中的JSON数据创建一个表,然后通过Redshift Spectrum查询和解析。

背景:
JSON数据来自DynamoDB流,并且深度嵌套。 JSON的第一级具有一组一致的元素集:键,NewImage,OldImage,SequenceNumber,roximateCreationDateTime,SizeBytes和EventName。唯一的变化是,有些记录没有NewImage,有些没有OldImage。但是,在此第一级以下,架构会有很大不同。

理想情况下,我们只想使用Glue来解析这第一个JSON级别,并且基本上将较低级别的JSON视为大型STRING对象(然后根据需要使用Redshift Spectrum对其进行解析)。当前,我们正在将整个记录加载到Redshift中的单个VARCHAR列中,但是记录已接近Redshift中数据类型的最大大小(最大VARCHAR长度为65535)。因此,我们希望在记录达到Redshift之前执行第一级解析。

到目前为止,我们已经尝试/引用了以下内容:


将AWS Glue Crawler指向S3存储桶会导致数百个表具有一致的顶级架构(上面列出的属性),但STRUCT元素中更深层次的架构有所不同。我们还没有找到一种创建可从所有这些表中读取并将其加载到单个表中的Glue ETL作业的方法。
手动创建表并没有取得成功。我们尝试将每一列设置为STRING数据类型,但是该作业未能成功加载数据(大概是因为这会涉及从STRUCT到STRING的某种转换)。在将列设置为STRUCT时,它需要一个已定义的模式-但这正是从一条记录到另一条记录的不同之处,因此我们无法提供适用于所有相关记录的通用STRUCT模式。
AWS Glue Relationalize transform很有意思,但不是我们在这种情况下要寻找的内容(因为我们想保持一些JSON完整,而不是完全扁平化)。 Redshift Spectrum直到几周前都支持scalar JSON数据,但这不适用于我们正在处理的嵌套JSON。这些似乎都无法帮助处理Glue Crawler创建的数百个表。


题:
我们将如何使用Glue(或其他方法)来仅解析这些记录的第一级-而忽略顶层元素下方的各种模式-以便我们可以从Spectrum进行访问或将其物理加载到红移?

我是胶水新手。我花了很多时间在Glue文档中,并浏览了论坛上的(稀疏的)信息。我可能会遗漏一些明显的东西-也许这是目前形式的Glue的局限性。欢迎任何建议。

谢谢!

最佳答案

我不确定您是否可以使用表定义来执行此操作,但是可以通过使用映射函数将顶级值转换为JSON字符串来使用ETL作业来完成此操作。文档:[link]

import json

# Your mapping function
def flatten(rec):
    for key in rec:
        rec[key] = json.dumps(rec[key])
    return rec

old_df = glueContext.create_dynamic_frame.from_options(
    's3',
    {"paths": ['s3://...']},
    "json")

# Apply mapping function f to all DynamicRecords in DynamicFrame
new_df = Map.apply(frame=old_df, f=flatten)


从这里开始,您可以选择导出到S3(也许以Parquet或其他某种列式格式进行优化以进行查询),或者从我的理解中直接导出到Redshift,尽管我没有尝试过。

关于amazon-redshift - AWS Glue:如何使用各种模式处理嵌套JSON,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49458328/

10-11 10:45