对象内部定义的 Apache-Spark UDF 引发“没有可用于字符串的 TypeTag”

Posted

技术标签:

【中文标题】对象内部定义的 Apache-Spark UDF 引发“没有可用于字符串的 TypeTag”【英文标题】:Apache-Spark UDF defined inside object raises "No TypeTag available for String" 【发布时间】:2018-05-22 17:30:22 【问题描述】:

在交互式会话期间复制粘贴函数与使用 sbt 编译时,我得到了不同的行为。

Minimal, Complete, and Verifiable example 用于互动会话:

$ sbt package 
[error] src/main/scala/xxyy.scala:6: No TypeTag available for String
[error]     val correctDiacritics = udf((s: scala.Predef.String) => 
[error]                                ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 9 s, completed May 22, 2018 2:22:52 PM
$ cat src/main/scala/xxyy.scala 
package xxx.yyy
import org.apache.spark.sql.functions.udf
object DummyObject 
    val correctDiacritics = udf((s: scala.Predef.String) => 
            s.replaceAll("è","e")
            .replaceAll("é","e")
            .replaceAll("à","a")
            .replaceAll("ç","c")
            )

上述代码无法编译。但是在交互式会话期间:

// During the `spark-shell` session.
// Entering paste mode (ctrl-D to finish)
import org.apache.spark.sql.functions.udf
object DummyObject 
val correctDiacritics = udf((s: scala.Predef.String) => 
    s.replaceAll("è","e")
    .replaceAll("é","e")
    .replaceAll("à","a")
    .replaceAll("ç","c")
)

// Exiting paste mode, now interpreting.
// import org.apache.spark.sql.functions.udf
// defined object DummyObject
// Proceeds sucessfully.

版本:

我正在使用Scala 2.11

我正在使用Spark 2.1.0

built.sbt:

name := "my_app"

version := "0.0.1"

scalaVersion := "2.11.12"

resolvers ++= Seq(
Resolver sonatypeRepo "public",
Resolver typesafeRepo "releases"
)
resolvers += "MavenRepository" at "https://mvnrepository.com/"

libraryDependencies ++= Seq(
// "org.apache.spark" %% "spark-core" % "2.1.0",
// "org.apache.spark" %% "spark-sql" % "2.1.0",
//"org.apache.spark" %% "spark-core_2.10" % "1.0.2",
// "org.apache.spark" %
"org.apache.spark" % "spark-sql_2.10" % "2.1.0",
"org.apache.spark" % "spark-core_2.10" % "2.1.0",
"org.apache.spark" % "spark-mllib_2.10" % "2.1.0"
)

相关问题:

udf No TypeTag available for type string.

接受的答案并不能解决问题。

Spark, sbt package -- No TypeTag available.

截至 2018 年 5 月 22 日没有答复。

No typeTag available Error in scala spark udf.

截至 2018 年 5 月 22 日没有答复。

Spark UDF error no TypeTag available for string.

截至 2018 年 5 月 22 日没有答复。

【问题讨论】:

【参考方案1】:

您的构建定义不正确:

您使用 Scala 2.11.12 构建您的项目 但使用 Scala 2.10 构建的 Spark 依赖项

由于 Scala 在主要版本之间不兼容二进制,因此会出现错误。

最好使用%%,而不是嵌入Scala版本:

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-sql" % "2.1.0",
  "org.apache.spark" %% "spark-core" % "2.1.0",
  "org.apache.spark" %% "spark-mllib" % "2.1.0"
)

否则请确保使用正确的构建:

libraryDependencies ++= Seq(
  "org.apache.spark" % "spark-sql_2.11" % "2.1.0",
  "org.apache.spark" % "spark-core_2.11" % "2.1.0",
  "org.apache.spark" % "spark-mllib_2.11" % "2.1.0"
)

【讨论】:

以上是关于对象内部定义的 Apache-Spark UDF 引发“没有可用于字符串的 TypeTag”的主要内容,如果未能解决你的问题,请参考以下文章

定义一个接受 Spark DataFrame 中对象数组的 UDF?

Pyspark UDF 中自定义 Python 对象的使用

Apache-Spark 作为日志存储

将 Excel UDF 放入 Worksheet 对象(而不是在模块中)

Pyspark 子字符串在 UDF 内部不起作用

实现一个 java UDF 并从 pyspark 调用它