【问题标题】:Querying optional nested JSON fields in Athena在 Athena 中查询可选的嵌套 JSON 字段
【发布时间】:2020-08-01 11:48:50
【问题描述】:

我的 json 数据看起来像:

{ "col1" : 123, "metadata" : { "opt1" : 456, "opt2" : 789 } }

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

我的查询是:

select col1, metadata.opt1 from "db-name".tablename

如果opt1 不存在于任何行中,我希望这将返回所有行,opt1 列为空白,但如果metadata 中没有opt1 行,则爬虫运行(并且在运行查询时可能仍然不存在于数据中,因为它是可选的),查询失败,并且:

SYNTAX_ERROR: line 2:1: Column '"metadata"."opt1"' cannot be resolved

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

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

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

感谢您的任何想法。

【问题讨论】:

    标签: json amazon-web-services aws-glue amazon-athena


    【解决方案1】:

    这可能不是您想听到的,但我建议您不要使用 Glue Crawler。这只是当您的用例不完全符合其设计的用例时它所产生问题的冰山一角(参见例如this questionthis questionthis questionthis question、或this question)。

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

    无论您使用何种方法,使用可选字段使表格保持最新将会很复杂。如果您只添加,则可以在添加具有更多列的新分区时更新表的列(如果您使用 Athena 执行此操作,请在添加分区之前执行此操作),但另一种方法是简单地键入 metadata 列作为 STRING 并使用 JSON 函数来提取查询中的属性(参见例如 this question/answer)。

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

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

    这听起来可能比使用 Glue Crawler 更复杂,如果 Glue Crawler 真的按照您的预期工作,那么它会是。由于它们的工作效果不是很好,所以工作量会少很多。

    【讨论】:

      【解决方案2】:

      您可以使用 try 来解决您的问题。

          select col1, try(metadata.opt1) from "db-name".tablename
      

      【讨论】:

      • 不幸的是,这不起作用。 SYNTAX_ERROR: line 2:5: Column '"metadata"."opt1"' cannot be resolved
      猜你喜欢
      • 2019-04-18
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      • 1970-01-01
      • 1970-01-01
      • 2019-09-25
      • 2020-09-04
      • 1970-01-01
      相关资源
      最近更新 更多