Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 将包含无效字符的嵌套字段从Spark 2导出到Parquet_Apache Spark_Spark Dataframe_Parquet - Fatal编程技术网

Apache spark 将包含无效字符的嵌套字段从Spark 2导出到Parquet

Apache spark 将包含无效字符的嵌套字段从Spark 2导出到Parquet,apache-spark,spark-dataframe,parquet,Apache Spark,Spark Dataframe,Parquet,我正在尝试使用spark 2.0.2将JSON文件转换为拼花地板 JSON文件来自外部源,因此在模式到达之前无法对其进行更改 该文件包含属性映射。属性名在我收到文件之前是未知的 属性名称包含不能在拼花地板中使用的字符 空格和equals字符都不能用于拼花地板,我得到以下错误: org.apache.spark.sql.AnalysisException: Attribute name "name=attribute" contains invalid character(s) among "

我正在尝试使用spark 2.0.2将JSON文件转换为拼花地板

  • JSON文件来自外部源,因此在模式到达之前无法对其进行更改
  • 该文件包含属性映射。属性名在我收到文件之前是未知的
  • 属性名称包含不能在拼花地板中使用的字符
空格和equals字符都不能用于拼花地板,我得到以下错误:

org.apache.spark.sql.AnalysisException: Attribute name "name=attribute" contains invalid character(s) among " ,;{}()\n\t=". Please use alias to rename it.;
到目前为止,我发现唯一有效的解决方案是使用修改过的模式重新加载数据。新模式将把属性加载到映射中

Dataset<Row> newData = sql.read().json(path);
StructType newSchema = (StructType) toMapType(newData.schema(), null, "attributes");
newData = sql.read().schema(newSchema).json(path);
Dataset newData=sql.read().json(路径);
StructType newSchema=(StructType)toMapType(newData.schema(),null,“attributes”);
newData=sql.read().schema(newSchema).json(path);

private数据类型toMapType(数据类型DataType,字符串fullColName,字符串col){
if(数据类型instanceof StructType){
StructType StructType=(StructType)数据类型;
列表重命名=Arrays.stream(structType.fields()).map(
f->toMapType(f,fullColName==null?f.name():fullColName+““+f.name(),col)).collect(Collectors.toList());
返回新的StructType(重命名为.toArray(新的StructField[重命名为.size()]);
}
返回数据类型;
}
私有StructField toMapType(StructField StructField,String fullColName,String col){
if(fullColName.equals(col)){
返回新的StructField(col,new-MapType(DataTypes.StringType,DataTypes.LongType,true),true,Metadata.empty());
}else if(col.startsWith(fullColName)){
返回新的StructField(StructField.name()、toMapType(StructField.dataType()、fullColName、col)、StructField.nullable()、StructField.metadata());
}
返回结构域;
}

我对
@:
也有同样的问题

在我们的例子中,我们解决了美化数据帧的问题

  val ALIAS_RE: Regex = "[_.:@]+".r
  val FIRST_AT_RE: Regex = "^_".r

  def getFieldAlias(field_name: String): String = {
    FIRST_AT_RE.replaceAllIn(ALIAS_RE.replaceAllIn(field_name, "_"), "")
  }

  def selectFields(df: DataFrame, fields: List[String]): DataFrame = {
    var fields_to_select = List[Column]()
    for (field <- fields) {
      val alias = getFieldAlias(field)
      fields_to_select +:= col(field).alias(alias)
    }

    df.select(fields_to_select: _*)
  }
将被转换的[对象,架构。@类型,架构。name@id]@(在您的情况下,=)将为SparkSQL创建问题

所以在我们选择字段之后,您可以以
[对象、模式类型、模式名称\u id]。恭维的数据帧。

我通过以下方式解决了问题:

  val ALIAS_RE: Regex = "[_.:@]+".r
  val FIRST_AT_RE: Regex = "^_".r

  def getFieldAlias(field_name: String): String = {
    FIRST_AT_RE.replaceAllIn(ALIAS_RE.replaceAllIn(field_name, "_"), "")
  }

  def selectFields(df: DataFrame, fields: List[String]): DataFrame = {
    var fields_to_select = List[Column]()
    for (field <- fields) {
      val alias = getFieldAlias(field)
      fields_to_select +:= col(field).alias(alias)
    }

    df.select(fields_to_select: _*)
  }
df.toDF(df
    .schema
    .fieldNames
    .map(name => "[ ,;{}()\\n\\t=]+".r.replaceAllIn(name, "_")): _*)

我将所有不正确的符号替换为“u”。

您得到解决方案了吗?我仍在使用我发布的解决方案。不应将其标记为重复。这个问题是关于嵌套列的,与另一个问题完全不同@eliasah你怎么看?这只适用于没有嵌套字段的模式,OP的问题是关于嵌套字段的。你可以重做任何你想要的模式。您只需要实现scheme树,并对所有名称应用regexp模式。如何实现树下降超出了这个问题的范围
private DataType toMapType(DataType dataType, String fullColName, String col) {
    if (dataType instanceof StructType) {
        StructType structType = (StructType) dataType;

        List<StructField> renamed = Arrays.stream(structType.fields()).map(
            f -> toMapType(f, fullColName == null ? f.name() : fullColName + "." + f.name(), col)).collect(Collectors.toList());
        return new StructType(renamed.toArray(new StructField[renamed.size()]));
    }
    return dataType;
}

private StructField toMapType(StructField structField, String fullColName, String col) {
    if (fullColName.equals(col)) {
        return new StructField(col, new MapType(DataTypes.StringType, DataTypes.LongType, true), true, Metadata.empty());
    } else if (col.startsWith(fullColName)) {
        return new StructField(structField.name(), toMapType(structField.dataType(), fullColName, col), structField.nullable(), structField.metadata());
    }
    return structField;

}
  val ALIAS_RE: Regex = "[_.:@]+".r
  val FIRST_AT_RE: Regex = "^_".r

  def getFieldAlias(field_name: String): String = {
    FIRST_AT_RE.replaceAllIn(ALIAS_RE.replaceAllIn(field_name, "_"), "")
  }

  def selectFields(df: DataFrame, fields: List[String]): DataFrame = {
    var fields_to_select = List[Column]()
    for (field <- fields) {
      val alias = getFieldAlias(field)
      fields_to_select +:= col(field).alias(alias)
    }

    df.select(fields_to_select: _*)
  }
{ 
  object: 'blabla',
  schema: {
    @type: 'blabla',
    name@id: 'blabla'
  }
}
df.toDF(df
    .schema
    .fieldNames
    .map(name => "[ ,;{}()\\n\\t=]+".r.replaceAllIn(name, "_")): _*)