我正在尝试读取一个 ElasticSearch 索引,该索引包含数百万个文档,每个文档具有可变数量的字段。我有一个架构,其中有1000个字段,每个字段都有自己的名称和类型。
现在,当我创建 RDD 槽 ES-Hadoop 连接器,然后通过指定架构将其转换为 DataFrame 时,它无法显示-
输入行没有预期的数量的值 模式
我有几个问题。 1.是否可能有一个 RDD / DF ,其中行包含可变数量的字段?如果不是,除了为每列中的缺失字段添加空值之外,还有什么选择?
我看到默认情况下,当我使用StringType
调用时, Spark 会将所有内容转换为sc.newAPIHadoopRDD()
。如何根据架构中的字段名称对它们进行类型转换以更正类型?某种映射?
我想以 Parquet 格式编写此文件,并将模式添加到文件中。与具有1000个字段的架构相比,那些缺少的字段会发生什么情况。
答案 0 :(得分:1)
您不能具有可变的列数,但是可以使用集合类型的一列,例如Array或Map,在python中对应于字典。这使您可以在列中存储长度可变的数据。否则,您需要为架构中的每个列都有一个值。通常,您会用空值填充缺失值。
如果您已经有一个数据框,并且您有一个函数get_column_type
从列名中获取类型名称,则可以像这样重铸整个数据框:
import pyspark.sql.functions as F
select_expressions = [ F.col(column_name).cast(get_column_type(column_name)) for column_name in column_list]
recasted_df = df.select(*select_expressions)
镶木地板文件将具有数据框中具有的任何列。如果要在文件中包含1000个字段,则它们必须在数据框中,因此您必须用空值或其他某个值来填充缺失的值。
现在,如果将所有这些点放在一起,则可能需要执行以下操作:
id
字段和MapType类型的doc
字段的行中。explode
doc字段,因此您现在有3列:id
,key
和value
,其中的每个键为一行每个文档。此时,您可以写入镶木地板文件并完成该过程。如果您想要具有完整架构的数据框,则必须执行以下额外步骤:
pivoted_df = df.groupBy('id').pivot('key').agg(F.first('value')
df = df.withColumn('new_column', lit(None).cast(StringType())
id
。您可以将其写入镶木地板,它将在您的大架构中包含所有列。