【问题标题】:Spark extract nested JSON array items using purely SQL-querySpark 使用纯 SQL 查询提取嵌套的 JSON 数组项
【发布时间】:2020-01-27 23:51:35
【问题描述】:

注意:这不是以下(或其他几个类似讨论)的重复


我有一个Hive 表,我必须阅读并完全通过Spark-SQL-query 进行处理。该表有一个string-type 列,其中包含来自 API 的JSON 转储;不出所料,它具有深度嵌套的字符串化 JSON

让我们举个例子(它描述了我正在尝试处理的数据的确切深度/复杂性)

{
    "key1": ..
    "key2": ..
    ..
    "bill_summary": {
        "key1": ..
        "key2": ..
        ..
        "items": [
            {
                "item": {
                    "key1": ..
                    "key2": ..
                    ..
                    "type": "item_type_1"
                    ..
                    "total_cost": 57.65
                    ..
                }
            },
            {
                "item": {
                    "key1": ..
                    "key2": ..
                    ..
                    "total_cost": 23.31
                    ..
                }
            }
            ..
            {
                "item": {
                    "key1": ..
                    "key2": ..
                    ..
                    "type": "item_type_1"
                    ..
                }
            }
        ]
        ..
    }
    ..
}

我对@9​​87654333@ 数组感兴趣。我可以通过

get_json_object(get_json_object('$.bill_summary'), '$.items') AS items

问题来了

  • 我需要从数组中取出所有 (type, total_cost) 元组
  • 但我只需要同时存在这两个条目的条目,而几个 item 对象具有其中一个或一个都没有

  • 虽然我还设法将所有 type 字段和 total_cost 字段分别选择到 两个单独的数组中,但由于上述第二个限制(缺少字段),我最终 失去关系
  • 我最终得到(使用以下 sn-p)是两个数组(可能具有不同的长度),但不确定每个数组的对应元素是否属于同一项目

这个 sn-p 只列出了我相当长的 SQL 查询的一部分。它雇用CTE

..
split(get_json_object(get_json_object(var6, '$.bill_summary'), '$.items[*].item.type'), ',') AS types_array,
split(get_json_object(get_json_object(var6, '$.bill_summary'), '$.items[*].item.total_cost'), ',') AS total_cost_array
..

现在是限制

  • 我无法控制源 Hive 表架构或其数据
  • 我想使用 SparkSQL-query 来做到这一点
  • 无法使用DataFrame 操作
  • 我不想雇用registered udf(我将其保留为最后的手段)

我在文档和论坛上花了几个小时,但 Spark-SQL docs 很少,discussions 主要围绕 DataFrame API,我无法使用。这个问题甚至可以通过单独的 SQL 查询来解决吗?

【问题讨论】:

    标签: apache-spark-sql


    【解决方案1】:

    经过数小时的网络搜索,this 的回答提示我可以在 spark-sql 中字符串化 JSON 数组转换为结构数组。最后这就是我所做的

         ..
         var6_items AS
      (SELECT hash_id,
              entity1,
              dt,
              get_json_object(get_json_object(var6,'$.bill_summary'), '$.items[*].item') AS items_as_string
       FROM rows_with_appversion
       WHERE appversion >= 14),
    
         filtered_var6_items AS
      (SELECT *
       FROM var6_items
       WHERE items_as_string IS NOT NULL
         AND items_as_string != '')
    
        SELECT from_json(items_as_string, 'array<struct<type:string,total_cost:string>>') AS items_as_struct_array
        FROM filtered_var6_items
         ..
    

    解释

    • 表达式get_json_object(get_json_object(var6,'$.bill_summary'), '$.items[*].item') AS items_as_string 导致items_as_string 包含以下(字符串化)JSON(请注意,每个item 周围的一层冗余嵌套也已被删除)
    [
      {
        "key1": "val1",
        "key2": "val2",
        "type": "item_type_1",
        "total_cost": 57.65
      },
      {
        "key1": "val1",
        "key2": "val2",
        "total_cost": 57.65
      }
      ..
      {
        "key1": "val1",
        "key2": "val2",
        "type": "item_type_1"
      }
    ]
    
    • 此后,from_json 函数允许将上述结构转换为arraystructs。一旦获得,我可以 filter 结构同时具有 typetotal_cost 而不是 NULL

    参考文献

    【讨论】:

      猜你喜欢
      • 2021-06-22
      • 1970-01-01
      • 2014-10-03
      • 1970-01-01
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多