在 Athena 中查询可选嵌套 JSON 字段

Lui*_*hys 2 json amazon-web-services amazon-athena aws-glue

我的 json 数据看起来像这样:

{ "col1" : 123, "metadata" : { "opt1" : 456, "opt2" : 789 } }
Run Code Online (Sandbox Code Playgroud)

其中各种元数据字段(有很多)是可选的,并且可能存在也可能不存在。

我的查询是:

select col1, metadata.opt1 from "db-name".tablename
Run Code Online (Sandbox Code Playgroud)

如果opt1不存在于任何行中,我希望这会返回该列为空白的所有行opt1,但是如果爬网程序运行时没有包含 in 的行opt1metadata并且当查询时可能仍然不存在于数据中)运行,因为它是可选的),查询失败,并显示:

SYNTAX_ERROR: line 2:1: Column '"metadata"."opt1"' cannot be resolved
Run Code Online (Sandbox Code Playgroud)

我可以在架构定义中手动指定这些字段(如果我不使用爬网程序),但它不会拾取可能到达的任何新元数据字段,并且指定静态架构似乎并不在雅典娜应该如何工作的精神。

如何让它按预期运行(最好不要放入虚拟行或自定义 SerDe)?

org.openx.data.jsonserde.JsonSerDe目前使用SerDe 。

感谢您的任何想法。

The*_*heo 5

这可能不是您想听到的,但我建议您不要使用 Glue Crawler。这只是当您的用例与它设计的用例不完全匹配时所产生的问题的冰山一角(例如,参见这个问题这个问题这个问题这个问题这个问题))。

\n\n

相反,使用 Glue Crawler 在工作时为您创建的任何内容手动创建表(您可以SHOW CREATE TABLE foo在 Athena 中获取表的 DDL)。然后使用 手动添加分区ALTER TABLE foo ADD PARTITION

\n\n

无论您使用什么方法,使用可选字段使表保持最新都会很复杂。如果您只添加过,则可以在添加具有更多列的新分区时更新表的列(如果您使用 Athena 执行此操作,请在添加分区之前执行此操作),但另一种方法是简单地键入metadata列asSTRING并使用 JSON 函数提取查询中的属性(例如,请参阅此问题/答案)。

\n\n

我假设您正在使用 Glue Crawler 定期添加分区。如果您控制向 S3 添加数据的过程,我建议您在其中添加运行ALTER TABLE \xe2\x80\xa6 ADD PARTITION(或CreatePartition在 Glue API 中使用)的代码。

\n\n

如果您无法控制该代码,或者这会很不方便,您可以使用 Lambda 来解决问题。例如,如果您仅按时间分区,则可以每天运行一次并添加第二天的分区(S3 上不必有任何数据,您可以添加没有的分区)但包含数据,它只是元数据)。如果情况比这更复杂,您可以在 S3 上创建新文件时触发 Lambda 函数运行,并添加分区作为反应。

\n\n

这听起来可能比使用 Glue Crawler 更复杂,如果 Glue Crawler 确实按照您的预期工作,那就会是这样。由于它们实际上工作得不太好,所以工作量会少很多。

\n


归档时间:

查看次数:

1962 次

最近记录:

5 年,6 月 前