我在项目中使用Scala,我遇到以下情况:
我正在阅读csv文件,我有以下结构:
mail,file,action
ex1@...,file1,insert
ex2@...,file2,update
我的mongodb中有三个集合:用户,文件,操作和; Actions引用文件和用户ID。
架构将是这样的:
Action {
actionName: String,
userId: ObjectId,
fileId: ObjectId
}
问题是我在阅读csv时没有这些ID。它们是在阅读过程中创建的。所以我的主要问题是:如果用户和文件在您尝试使用它们时重新插入,如何引用它们。
我最初的解决方案是创建3个踏板以保存代码的每个部分并使用两个贴图:Map1 [userMail,Ids]和Map2 [fileName,Ids]。在数据库中插入用户或文件后,代码将采用各自的ID并放入地图中。
与此同时,我有一个保存动作的线程。这个线程在它们具有两个id时保持汇集这些映射。只要它有,它就会保存动作(让我们调用它"动作线程")。像这样:
while(filesMap.get(action.fileId) == None) {
Thread.sleep(1000)
}
while(usersMap.get(action.userId) == None) {
Thread.sleep(1000)
} ... //save code omitted for clarity
此代码有效,但问题是它太慢了。我相信"动作线程"正在使用其池来锁定映射,从而阻止从实际将数据保存到数据库的线程中进行一些写入。
所以,我的问题是:是否有一种更聪明的方式来通知"动作线程"那些ID在那里并删除了池代码,或者,在 scala 中是否有更好的方法可以开箱即用?
我在Javascript中使用promises和resolve做了类似的事情,但由于我使用Scala工作不到一个月,我不知道如何移植代码。
由于
答案 0 :(得分:1)
如果在您尝试使用这些用户和文件时重新插入这些用户和文件,该如何引用它们
您需要加入。
mongodb的
在真实数据库中流式传输所有内容并在那里进行连接。在Scala中完成它基本上是手工重新实现半个数据库...
如果你有无限的内存,你可以在Scala不可变集合中加载所有内容:
val filesMap: Map[Int, File] = ...
val userMap: Map[Int, User] = ...
val actions: Stream[Action] =
csv.lines.map(csvParser).flatMap { case (actionName, userId, fileId) =>
for {
file <- filesMap.get(fileId)
user <- userMap.get(userId)
} yield
Action(actionName, user, file)
}
答案 1 :(得分:0)
Scala对象不是为多线程访问而设计的。你想在scala中使用actor。
但我想你需要做投票。有可能,只需使用Java
java.util.concurrent.ConcurrentHashMap中 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html
Scala适用于Java类。