客观的
我有一个 S3 文件夹,里面装满了不同模式的 json 文件,包括数组(一个 dynamodb 备份,碰巧)。然而,虽然模式有所不同,但所有文件都包含一些常见元素,例如“id”或“name”,以及不同长度的嵌套数组,例如“选定项目”。我希望能够在闲暇时解析出这些元素。
我有一种使用外部 ETL 工具 (KNIME) 的工作方法,我希望通过 Glue 以无服务器方式复制该工具。
背景
工作方法是:
- 使用 Spectrum 将所有 S3 数据加载为外部表,每个 json 记录作为单个
varchar(65535)
条目。 json_extract_path_text
使用 Redshift SQL 函数解析出我需要的元素,包括特定的数组,例如json_array_length
- 通过对数组索引的引用表进行交叉连接来规范化所需的 json 数组
- 执行所需的表连接并写入 Redshift 以供 Tableau 使用
现在,这似乎是一项适合 Glue 的任务。即,我想要做的是,要么:
使用 Spectrum 加载所有数据,如上
在 Glue 中,从 Spectrum 表创建一个动态框架
使用诸如
pyspark.sql.functions.explode()
或可能使用 Glue 的 Relationalize 变换之类的函数从上述动态帧中解析数据
或者:
- 将所有标量数据抓取到单个 Glue 模式中(假设 Glue 尚不支持 JSON 数组)
- 使用上述方法之一解析 JSON 并分解数组
到目前为止的结果
不幸的是,我无法让这些方法中的任何一种发挥作用。对于各种方法,阻滞剂是:
- 使用 Glue 抓取 json 数据 - 根据这篇文章,Glue 的解析器启发式方法决定源的各种模式差异太大而无法与单个源相关,因此将它们解析为一堆不同的表。有一个爬虫只需爬取每个文件以生成一个表,该表具有类型为 varchar(65535) 的单列,每行包含一个 json 条目,但似乎没有任何 Glue 分类器 JSON 路径表达式可以实现这一目标。
'single varchar(65535) column' 方法可以通过将数据加载为 Spectrum 中的外部表来实现,但似乎 Spectrum 表无法作为动态帧加载到 Glue 中(请注意,相关表存在于 Glue 目录中它显示为具有预期的 varchar(65535) 架构)。在 Zeppelin Notebooks 工作,我发现
newFrame = glueContext.create_dynamic_frame.from_catalog(database="<spectrum database>", table_name="<spectrum one column varchar table>")
运行成功,但是会生成一个带有
newFrame.count() = 0
和的表newFrame.toDF().show(n)
,对于任何 n 值都会生成以下形式的奇数输出:++
||
++
++
简而言之,pySpark 似乎无法通过 Glue 直接使用 Spectrum 表。
使用 Crawler 抓取 Spectrum 表。在这里,我通过与我的 Redshift 集群的 Glue 连接将爬虫指向了所需的表。但是,这会导致 S3 端点验证失败,我还不能解决这个问题。我不愿意深入研究 VPC 配置,因为我已经非常不确定将 Crawler 指向 Spectrum 表是否是正确的方法。
简而言之,我发现无法使用 Glue Crawler 或 Glue 和 Redshift Spectrum 的组合在 S3 上动态摄取和解析非标量 json。这可以说不是一项深奥的任务——事实上,任何想要一种相对自动化的方法来报告来自基于 dynamodb 的 Web 应用程序的数据的人都需要实现它。
问题
所以我的问题是,在一个声明中:有什么方法可以使用 Glue 解析 S3 上具有不一致架构的非标量 json 文件(另外,可能还有其他 AWS 服务,例如 RS Spectrum)?