为什么MongoDB Spark Connector会因AbstractMethodError而失败?

时间:2016-08-10 11:21:18

标签: mongodb apache-spark apache-spark-sql

我正在尝试在远程mongodb集合中插入spark sql数据帧。 以前我用MongoClient编写了一个java程序来检查远程集合是否可以访问,并且我已经成功完成了。

我目前的火花代码如下 -

scala> val sqlContext = new org.apache.spark.sql.hive.HiveContext(sc)
warning: there was one deprecation warning; re-run with -deprecation for details
sqlContext: org.apache.spark.sql.hive.HiveContext = org.apache.spark.sql.hive.HiveContext@1a8b22b5
scala> val depts = sqlContext.sql("select * from test.user_details")
depts: org.apache.spark.sql.DataFrame = [user_id: string, profile_name: string ... 7 more fields]
scala> depts.write.options(scala.collection.Map("uri" -> "mongodb://<username>:<pwd>@<hostname>:27017/<dbname>.<collection>")).mode(SaveMode.Overwrite).format("com.mongodb.spark.sql").save()

Ths发出以下错误 -

java.lang.AbstractMethodError: com.mongodb.spark.sql.DefaultSource.createRelation(Lorg/apache/spark/sql/SQLContext;Lorg/apache/spark/sql/SaveMode;Lscala/collection/immutable/Map;Lorg/apache/spark/sql/Dataset;)Lorg/apache/spark/sql/sources/BaseRelation;
  at org.apache.spark.sql.execution.datasources.DataSource.write(DataSource.scala:429)
  at org.apache.spark.sql.DataFrameWriter.save(DataFrameWriter.scala:211)
  ... 84 elided

我还尝试了以下错误:

scala> depts.write.options(scala.collection.Map("uri" -> "mongodb://<username>:<pwd>@<host>:27017/<database>.<collection>")).mode(SaveMode.Overwrite).save()
java.lang.IllegalArgumentException: 'path' is not specified
  at org.apache.spark.sql.execution.datasources.DataSource$$anonfun$17.apply(DataSource.scala:438)
  at org.apache.spark.sql.execution.datasources.DataSource$$anonfun$17.apply(DataSource.scala:438)
  at scala.collection.MapLike$class.getOrElse(MapLike.scala:128)
  at org.apache.spark.sql.execution.datasources.CaseInsensitiveMap.getOrElse(ddl.scala:117)
  at org.apache.spark.sql.execution.datasources.DataSource.write(DataSource.scala:437)
  at org.apache.spark.sql.DataFrameWriter.save(DataFrameWriter.scala:211)
  ... 58 elided

我已导入以下软件包 -

import org.apache.spark.{SparkConf, SparkContext}

import org.apache.spark.sql.SQLContext

import com.mongodb.casbah.{WriteConcern => MongodbWriteConcern}

import com.mongodb.spark.config._

import org.apache.spark.sql.hive.HiveContext

import org.apache.spark.sql._

depts.show()按预期工作,即。数据框已成功创建。

请有人就此向我提出任何建议/意见。 感谢

2 个答案:

答案 0 :(得分:1)

假设您使用的是MongoDB Spark Connector v1.0,您可以像下面一样保存DataFrames SQL:

// DataFrames SQL example 
df.registerTempTable("temporary")
val depts = sqlContext.sql("select * from test.user_details")
depts.show()
// Save out the filtered DataFrame result
MongoSpark.save(depts.write.option("uri", "mongodb://hostname:27017/database.collection").mode("overwrite"))

有关详细信息,请参阅MongoDB Spark Connector: Spark SQL

有关使用docker的MongoDB和Spark的简单演示,请参阅MongoDB Spark Docker: examples.scala - dataframes

答案 1 :(得分:0)

看看这个错误,并想办法解决这个错误。这是由于用于MongoDB的Spark连接器和您使用的Spark之间的Spark版本不匹配。

  

java.lang.AbstractMethodError:com.mongodb.spark.sql.DefaultSource.createRelation(Lorg / apache / spark / sql / SQLContext; Lorg / apache / spark / sql / SaveMode; Lscala / collection / immutable / Map; Lorg / apache / spark / sql / Dataset;)Lorg / apache / spark / sql / sources / BaseRelation;

引用java.lang.AbstractMethodError的javadoc:

  

当应用程序尝试调用抽象方法时抛出。通常,此错误由编译器捕获;如果自从上次编译当前执行的方法以来某个类的定义发生了不兼容的更改,则只有在运行时才会发生此错误。

这几乎可以解释您的经验(请注意以“此错误只能在运行时发生”开头的部分)。

我的猜测是栈跟踪Lorg/apache/spark/sql/Dataset方法中的DefaultSource.createRelation部分正是罪魁祸首。

换句话说,that line使用的data: DataFrame而不是Dataset在这个方向上是不兼容的,即DataFrame就是Dataset[Row]的{​​{3}} ,但任何数据集都不是DataFrame,因此是运行时错误。

override def createRelation(sqlContext: SQLContext, mode: SaveMode, parameters: Map[String, String], data: DataFrame): BaseRelation