插入带有reactivemongo的文档并在之后获取它

时间:2013-11-14 14:41:49

标签: scala playframework-2.0 reactivemongo

将值插入持久层并返回结果对象时,通常最好提取新创建的实体,而不是再次返回输入数据。

当我尝试使用reactivemongo在Scala中执行此操作时,我偶然发现了我的语言技能。

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 个答案:

答案 0 :(得分:1)

我想说惯用的Play / 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收益率。