客观
我有一个S3文件夹,里面充满了具有不同模式(包括数组)的json文件,包括数组(动态备份)。但是,尽管架构有所不同,但所有文件都包含一些通用元素,例如'id'或'name',以及不同长度的嵌套数组,例如'selected items'。我希望能够在闲暇时解析这些元素。
我有一个使用外部ETL工具(KNIME)的可行方法,我希望通过Glue以无服务器方式复制该工具。
背景
工作方法是:
varchar(65535)
条目。 json_extract_path_text
和json_array_length
之类的Redshift SQL函数解析出我需要的元素,包括特定的数组现在,这似乎是应该适合Glue的任务。即,我想做的是:
如上所述,使用Spectrum加载所有数据
在Glue中,从Spectrum表中创建一个动态框架
使用pyspark.sql.functions.explode()
之类的功能,或者使用Glue的Relationalize变换,从上述动态帧中解析数据
或者:
到目前为止的结果
很遗憾,我无法使用这两种方法。对于各种方法,阻止者已成为:
“单个varchar(65535)列”方法可以通过在Spectrum中将数据作为外部表加载来实现,但是似乎Spectrum表不能作为动态帧加载到Glue中(请注意,相关的该表存在于Glue目录中,其中显示为具有预期的varchar(65535)模式)。在Zeppelin笔记本电脑上工作时,我发现了
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表一起使用。
使用“搜寻器”搜寻“频谱”表。在这里,我已经通过与我的Redshift集群的Glue连接将搜寻器指向了所需的表。但是,这使我无法解决S3端点验证失败。鉴于我已经非常不确定是否将Crawler指向Spectrum表,因此我不愿深入研究VPC配置。
简而言之,我发现没有任何方法可以使用Glue Crawler或Glue和Redshift Spectrum的组合在S3上动态提取和解析非标量json。可以说这不是一项深奥的任务-实际上,任何想要相对自动化的方法来报告基于dynamodb的Web应用程序中的数据的人都需要实现这一目标。
问题
所以我的问题只用一条语句:是否有任何方法可以使用Glue(加上可能的其他AWS服务,例如RS Spectrum)来解析具有不一致模式的S3上的非标量json文件?
答案 0 :(得分:1)
所以我认为在后台发生了一些事情。
我假设您在Redshift Spectrum中定义了一个指向S3的外部表?如果是这样,那不是最好的方法。而是定义一个指向Glue数据目录中的表的外部模式。结果是RS Spectrum将在该Glue数据库中看到所有内容,而无需定义单独的表。
其次,您是否尝试过在Glue数据目录中手动定义表?我已经使用Parquet文件格式进行了广泛的测试,弄乱了表定义和文件内容。结果是,无论从该表中查询什么,它都只会返回表中定义的数据。因此,您可以定义一个具有“ id”,“ name”和“ selected items”字段的表,其他所有内容都将被忽略。
如果由于某种原因前一个命令似乎不起作用,则可以执行胶粘作业。这里要注意-始终只使用spark,不要使用任何与gele_context相关的东西。无论如何,您可以在spark.read.blaah中指定一个模式参数。使用它。
dataSchema = StructType([StructField("id",StringType(),True)
,StructField("name",StringType(),True)
,StructField("selected items",ArrayType(.. etc ...),True)
])
这样,您将获得相同的结果-它只会解析出您想要的数据。
最后的设置可能应该是这样的: