【问题标题】:spark2 sql deeply nested array structure with parquetspark2 sql深度嵌套数组结构与镶木地板
【发布时间】:2020-03-12 06:05:42
【问题描述】:

给定这样一个深度嵌套的 parquet 结构

|-- bet: struct (nullable = true)
|    |-- sides: array (nullable = true)
|    |    |-- element: struct (containsNull = true)
|    |    |    |-- side: string (nullable = true)
|    |    |    |-- betID: string (nullable = true)
|    |    |    |-- secondarybetID: string (nullable = true)
|    |    |    |-- parties: struct (nullable = true)
|    |    |    |    |-- partyIDs: array (nullable = true)
|    |    |    |    |    |-- element: struct (containsNull = true)
|    |    |    |    |    |    |-- partyID: string (nullable = true)
|    |    |    |    |    |    |-- partyRole: integer (nullable = true)
|    |    |    |    |    |    |-- partySubGrp: struct (nullable = true)
|    |    |    |    |    |    |    |-- partySubIDs: array (nullable = true)
|    |    |    |    |    |    |    |    |-- element: struct (containsNull = true)
|    |    |    |    |    |    |    |    |    |-- partySubID: string (nullable = true)
|    |    |    |    |    |    |    |    |    |-- partySubIDType: integer (nullable = true)

考虑到一个赌注有几个方面,不知何故,我们只对边数数组中的第一边感兴趣。 如何找到partyRole为10的一方的参与方?

在 prestosql 中我可以做类似的事情

 SELECT 
        filter(bet.sides[1].parties.partyids, x -> x.partyrole=10)[1] as party10
    FROM 
        parquetbets
    WHERE 
        cardinality(filter(bet.sides[1].parties.partyids, x -> x.partyrole=10))>0

如何在 spark2 sql 中做同样的事情?

 SELECT bet.sides[1] from parquetbets 

在 spark2 sql 中,上面返回一个数组,在嵌套结构上没有进一步修剪的范围?

 SELECT bet.sides[1].parties from parquetbets

返回空值。我尝试了一些组合,但结果返回 WrappedArrayElements,它不提供查询嵌套数据的机制。 在 prestosql 中返回的结果包含字段名称,以便于继续深入研究结构。

有人能告诉我 spark2 sql 如何支持这个吗? 如果 spark2 sql 不能,那么 spark 数据帧如何做到这一点?

【问题讨论】:

    标签: apache-spark apache-spark-sql parquet trino spark2


    【解决方案1】:

    愚蠢的问题:您是否考虑过将 DataSet API 与编码器一起使用?它提供了一个功能性 API 来推理您的问题(这是一种更容易解决功能性问题的方法)。

    否则考虑分解您的数组以对展平数据进行推理(请参阅 org.apache.spark.sql.functions.explode)。

    scala 中的示例:

      case class PartyId(partyID: String, partyRole: Int)
      case class Party(partyIDs: Seq[PartyId])
      case class Side(side: String, betId: String, parties: Party)
      case class Bet(sides: Seq[Side])
    
      import spark.implicits._
      val ds = spark.read.load("my-bets.parquet").as[Bet]
    
      val firstSidesDS = ds.flatMap(_.sides.headOption) //take the first side if exists
    
      val result: Dataset[Side] = firstSidesDS.filter(_.parties.partyIDs.exists(_.partyRole == 10)) //Here I return sides for which there is at least a partyRole = 10
    

    【讨论】:

    • 你能举个例子吗?
    • 您使用的是 Scala、Java 还是 Python?
    • 刚刚添加了一个使用 Scala 和 Dataset API 的示例
    • 使用 spark sql 和 Java。我想通过编写 sql 来演示 sparksqls 查询 parquet 数据的能力。在这种情况下,它似乎可能达不到要求。 Prestosql 按预期工作。我有点失望 sparksql 返回包装数组,这无助于进一步“发现”数据。谢谢你会试试你的建议
    • 这会导致我再次使用编码器来描述模式,这似乎与已经拥有模式的直觉相反?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    • 2020-02-25
    • 2021-08-27
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    相关资源
    最近更新 更多