2013-11-14 97 views
1

向持久層中插入值並返回結果對象時,通常是取出新創建的實體而不是再次返回輸入數據的一種好方法。使用reactivemongo插入文檔並在之後獲取

當我嘗試在Scala中使用reactivemongo來做這件事時,我偶然發現我的語言技能。

def create(user: User): Future[User] = { 
val newUser = user.createOID() 

collection.insert(newUser).map { 

    case ok if ok.ok => { 
    for { 
     createdUser <- this.findOne(BSONDocument("_id" -> newUser._id)) 
    } yield { 

     createdUser match { 
     case None => throw new RuntimeException("Could not find just created user") 
     case Some(x) => x 
     } 
    } 
    } 
    case error => throw new RuntimeException(error.message) 
    } 
} 

凡findOne有簽名:

def findOne(query: BSONDocument): Future[Option[User]] 

我得到以下錯誤:

[error] found : scala.concurrent.Future[models.User] 
[error] required: models.User 
[error] createdUser <- this.findOne(BSONDocument("_id" -> newUser._id)) 
[error]   ^

如果我返回NEWUSER對象,一切都很好。

我想我有一個普遍的誤解,這裏發生了什麼 - 也許有一個更好的方法來獲取一次創建的對象。

回答

1

我要說的是地道的播放/ Scala的方式做到這一點是以下

def create(user: User): Future[Option[User]] = { 
    val newUser = user.createOID() 
    for { 
    nu <- collection.insert(newUser) 
    createdUser <- findOne(BSONDocument("_id" -> newUser._id)) 
    } yield { 
    createdUser 
    } 
} 

注意,這不會返回Future[Option[User]]而不是Future[User]在你的代碼。我相信Option[User]肯定是在這種情況下去的方式,因爲它實際上告訴客戶端此方法不能保證插入將成功(並且因此不需要運行時異常,因爲客戶端將對此方法的結果執行.map - 避免使用例外,如果你可以優雅地處理它們)。

您也可以檢查nu是否在收益率範圍內爲ok

+0

非常感謝 - 這看起來不錯,合乎邏輯,很有效! – DanielKhan

+0

生成一個必須在其他系統中唯一的唯一標識符是一個簡單的想法。什麼是保證這個createOID會生成一個唯一的字符串,這在MongoDB中將是唯一的? – sparkr

相關問題