我需要将我的RDD中的字段映射到另一个地图中的另一个字段UserDAO.users
我试图找出这里的映射但是还不能返回username
。当我进行foreach打印scala.concurrent.impl.Promise$DefaultPromise@7c4c5ddd
这是我的代码段:
rdd.map { l => {
l.map { case (k, v) => {
k match {
case "a_userid" => {
l.updated("a_username", userDAO.users.map(c => c.filter(f => f.userid == v.toInt)).map(y => y.map(e => e.username)))
}
case _ =>
}
}
}
}
}
基本上,
rdd
- RDD[Map[String, String]]
UserDAO.users - Future[Seq[User]]
- 其中User是案例类
并返回更新后的rdd
- RDD[Map[String, String]]
-
知道如何解决这个问题吗?
由于
答案 0 :(得分:1)
我已重写您的代码以使其正常工作。请注意,它涉及阻止,否则没有其他方法可以获得具体的RDD[Map[String, String]]
。
为了清楚起见,我省略了rdd.map
部分。
第一个变种。我使用了您在map
内阅读用户的方法。请注意,这是非常低效的,因为每次迭代都会读取所有用户,即1100万次:
// rdd.map ommitted
l.get("a_userid").flatMap {
userId:String =>
val newUserName:Option[String] =
Await.result(userDAO.users
.map(c => c.find(f => f.userid == userId.toInt))
.map(y => y.map(e => e.username)),
30 seconds
)
newUserName.map(l.updated("a_username", _))
}.getOrElse(l)
替代方法涉及事先将用户读取到地图。那张地图随后将播放给所有火花工人。由于你的地图不是很大,所以很好。这种方法效率更高,因为您在RDD
上每次迭代只执行一次地图查找,这很快。
val users:Map[Int, String] = Await.result(userDAO.users
.map(uss => uss.map(u => u.userid -> u.username).toMap),
30 seconds
)
// rdd.map ommitted
l.get("a_userid").flatMap {
userId:String =>
users.get(userId.toInt).map(l.updated("a_username", _))
}.getOrElse(l)
UPD :仅仅为了完整起见,这是另一个异步变体:
userDAO.users
.map(uss => uss.map(u => u.userid -> u.username).toMap)
.map { users:Map[Int, String] =>
rdd.map { l:Map[String, String] =>
l.get("a_userid").flatMap {
userId:String =>
users.get(userId.toInt).map(l.updated("a_username", _))
}.getOrElse(l)
}
}
它遵循与variant2相同的方法,但返回Future[RDD[Map[String, String]]]
而不是具体结果。