【发布时间】:2016-01-30 10:11:37
【问题描述】:
场景和问题: 我想根据查找表值向 JSON 对象添加两个属性,并将 JSON 插入 Mongo DB。我有保存查找表的广播变量。但是,正如您在代码中看到的那样,我无法在 foreachPartition 中访问它。它没有给我任何错误,只是没有显示任何内容。另外,因为它我无法将 JSON 插入 Mongo DB。我找不到对这种行为的任何解释。非常感谢任何解释或解决方法以使其工作。
这是我的完整代码:
object ProcessMicroBatchStreams {
val calculateDistance = udf {
(lat: String, lon: String) =>
GeoHash.getDistance(lat.toDouble, lon.toDouble) }
val DB_NAME = "IRT"
val COLLECTION_NAME = "sensordata"
val records = Array[String]()
def main(args: Array[String]): Unit = {
if (args.length < 0) {
System.err.println("Usage: ProcessMicroBatchStreams <master> <input_directory>")
System.exit(1)
}
val conf = new SparkConf()
.setMaster("local[*]")
.setAppName(this.getClass.getCanonicalName)
.set("spark.hadoop.validateOutputSpecs", "false")
/*.set("spark.executor.instances", "3")
.set("spark.executor.memory", "18g")
.set("spark.executor.cores", "9")
.set("spark.task.cpus", "1")
.set("spark.driver.memory", "10g")*/
val sc = new SparkContext(conf)
val ssc = new StreamingContext(sc, Seconds(60))
val sqc = new SQLContext(sc)
val gpsLookUpTable = MapInput.cacheMappingTables(sc, sqc).persist(StorageLevel.MEMORY_AND_DISK_SER_2)
val broadcastTable = sc.broadcast(gpsLookUpTable)
ssc.textFileStream("hdfs://localhost:9000/inputDirectory/")
.foreachRDD { rdd =>
//broadcastTable.value.show() // I can access broadcast value here
if (!rdd.partitions.isEmpty) {
val partitionedRDD = rdd.repartition(4)
partitionedRDD.foreachPartition {
partition =>
println("Inside Partition")
broadcastTable.value.show() // I cannot access broadcast value here
partition.foreach {
row =>
val items = row.split("\n")
items.foreach { item =>
val mongoColl = MongoClient()(DB_NAME)(COLLECTION_NAME)
val jsonObject = new JSONObject(item)
val latitude = jsonObject.getDouble(Constants.LATITUDE)
val longitude = jsonObject.getDouble(Constants.LONGITUDE)
// The broadcast value is not being shown here
// However, there is no error shown
// I cannot insert the value into Mongo DB
val selectedRow = broadcastTable.value
.filter("geoCode LIKE '" + GeoHash.subString(latitude, longitude) + "%'")
.withColumn("Distance", calculateDistance(col("Lat"), col("Lon")))
.orderBy("Distance")
.select(Constants.TRACK_KM, Constants.TRACK_NAME).take(1)
if (selectedRow.length != 0) {
jsonObject.put(Constants.TRACK_KM, selectedRow(0).get(0))
jsonObject.put(Constants.TRACK_NAME, selectedRow(0).get(1))
}
else {
jsonObject.put(Constants.TRACK_KM, "NULL")
jsonObject.put(Constants.TRACK_NAME, "NULL")
}
val record = JSON.parse(jsonObject.toString()).asInstanceOf[DBObject]
mongoColl.insert(record)
}
}
}
}
}
sys.addShutdownHook {
ssc.stop(true, true)
}
ssc.start()
ssc.awaitTermination()
}
}
【问题讨论】:
-
MapInput从何而来,gpsLookUpTable的类型是什么? -
我有一个文件 GPSLOOKUPTABLE.json,它是一个查找表。 MapInput 函数使用该表的 SparkSQL 返回 Dataframe。函数为:
def cacheMappingTables(sc: SparkContext, sqlContext: SQLContext): DataFrame = { val allRows = sc.textFile("hdfs://localhost:9000/supportFiles/GeoHashLookUpTable") sqlContext.read.json(allRows).registerTempTable("GeoHashLookUpTable") val gpsLookUpTable = sqlContext.sql(" SELECT Lat, Lon, geoCode, TrackKM, TrackCode, TrackName, SubTrackCode, SubTrackName FROM GeoHashLookUpTable ") return gpsLookUpTable } -
@Patrick McGloin 请提供您的见解
-
@Erik Schmiege 请说出你的见解
-
我仍然被困在这里。任何人都知道如何并行处理并访问广播变量?
标签: json mongodb scala apache-spark apache-spark-sql