我正在使用官方代码MongoDB Spark Connector从MongoDB集合中读取Spark中的数据,并使用以下代码:
val spark = SparkSession.
builder().
appName("MongoDB to SQL").
getOrCreate()
val df = MongoSpark.load(spark, readConfig)
df.count()
readConfig是MongoDB的标准读取配置,可以正常工作。我遇到的问题是我从MongoDB以String的形式获取的某些日期/时间,它无法将其强制转换为Spark类型的TimestampValue:
INFO DAGScheduler: Job 1 failed: count at transfer.scala:159, took 3,138191 s
Exception in thread "main" org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 1.0 failed 1 times, most recent failure: Lost task 0.0 in stage 1.0 (TID 1, localhost, executor driver):
com.mongodb.spark.exceptions.MongoTypeConversionException: Cannot cast STRING into a TimestampType (value: BsonString{value='2999.12.31 14:09:34'})
at com.mongodb.spark.sql.MapFunctions$.com$mongodb$spark$sql$MapFunctions$$convertToDataType(MapFunctions.scala:200)
at com.mongodb.spark.sql.MapFunctions$$anonfun$3.apply(MapFunctions.scala:39)
at com.mongodb.spark.sql.MapFunctions$$anonfun$3.apply(MapFunctions.scala:37)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
根据我在df.printSchema()
之前调用.count()
时所看到的属性,看到的是
| | | |-- endDate: string (nullable = true)
在MongoDB中,endDate也存储为String。 Spark是否在此处执行其他步骤来检测模式?然后它无法投放...?通过查看https://github.com/mongodb/mongo-spark/blob/master/src/main/scala/com/mongodb/spark/sql/MapFunctions.scala#L181的源代码,它只能在那里进行简单的映射,而不能进行复杂的转换。
使用的版本:Mongo-Scala-Driver 2.4.0,Mongo-Spark-Connector 2.3.0,Spark 2.3.1
答案 0 :(得分:0)
如果我很了解您的问题,似乎您需要使用unix_timestamp
将日期作为字符串转换为时间戳(包括时区)并将其转换为TimestampType
如果您的df具有:[d:int,date:string]的df
val res = df.select($"id", $"date", unix_timestamp($"date", "yyyy/MM/dd HH:mm:ss").cast(TimestampType).as("timestamp"), current_timestamp(), current_date())
res.printSchema
root
|-- id: integer (nullable = false)
|-- date: string (nullable = true)
|-- timestamp: timestamp (nullable = true)
|-- currenttimestamp(): timestamp (nullable = false)
|-- currentdate(): date (nullable = false)`
您可以尝试查看以下示例: https://docs.databricks.com/_static/notebooks/timestamp-conversion.html
答案 1 :(得分:0)
可能是架构的另一个字段导致此错误,但不是'endDate'。您显示的没有错误信息说“ endDate”会导致此错误。
MongoDB Connector for Spark默认使用每个字段的1000个样本来构建其架构,因此,如果一个字段包含不同的数据类型(例如字符串数据类型和日期时间数据类型),MongoDB Connector for Spark可能不会对字符串数据进行采样,并将其作为日期时间数据类型。至少,当您使用计数方法时,连接器将尝试从mongodb加载数据以在spark数据帧中指定数据类型,并导致以下错误:“无法将STRING转换为TimestampType”
解决方案:
添加MongoDB Connector for Spark的样本数据以构建正确的架构。例如,在pyspark中:
df = session.read.format("com.mongodb.spark.sql.DefaultSource").option('sampleSize', 50000).load()