0

环境:玩!2.2.3、ReactiveMongo 0.10.0-SNAPSHOT

假设我有一个包含文档列表的页面(比如说“项目”)和一个按钮,该按钮弹出一个模式对话框,其中包含要填写的字段。按下 OK 按钮后,页面向后端发送一个带有 JSON 正文的请求:

{
    name: "Awesome Project", 
    url: "https://github.com/ab/cd", 
    repository: "git@github.com/ab/cd.git", 
    script: "empty"
}

后端将请求路由到Action定义的对象,如下所示:

  def projectsCollection: JSONCollection = db.collection[JSONCollection]("projects")

  def create = Action.async(parse.json) { request =>
    projectsCollection.insert(request.body) map {
      case LastError(true,_,_,_,Some(doc),_,_) =>  Created(JsObject(List(
        "result" -> JsString("OK") ,
        "doc" -> BSONFormats.toJSON(doc)
      )))
      case LastError(false, err, code, msg, _, _, _) => NotAcceptable(JsObject(List(
        "result" -> JsString("ERROR"),
        "error" -> JsString(err.getOrElse("unknown")),
        "code" -> JsNumber(code.getOrElse[Int](0)),
        "msg" -> JsString(msg.getOrElse("no messsage"))
      )))
    }
  }

LastError案例类有一个在请求响应正文中返回的参数,originalDocument: Option[BSONDocument]但它不是我期望的文档。我想要BSONObjectID填充或至少_id本身的文件。

试图检索新创建的文档使我陷入了死胡同,因为所有内容都包含在Future.

如何编写完成任务的优雅代码?

4

3 回答 3

2

一种可能的解决方案是自己生成_id字段并将其与请求正文连接:

val json = Json.obj("_id" -> BSONFormats.toJSON(BSONObjectID.generate)) ++ request.body.as[JsObject]

然后将该json值作为insert参数,放入成功的结果体中。

projectsCollection.insert(json) map {
  case LastError(true,_,_,_,Some(doc),_,_) =>  Created(JsObject(List(
    "result" -> JsString("OK") ,
    "doc" -> BSONFormats.toJSON(doc),
    "project" -> json
  )))
于 2013-10-29T13:30:12.303 回答
0

我是 Play、scala 和 reactivemongo 的新手,所以如果我的回答很丑,请原谅我的回答。但是,我确实得到了一个插入,然后开始工作:

def createUser = Action.async(parse.json) { request =>
/*
 * request.body is a JsValue.
 * There is an implicit Writes that turns this JsValue as a JsObject,
 * so you can call insert() with this JsValue.
 * (insert() takes a JsObject as parameter, or anything that can be
 * turned into a JsObject using a Writes.)
 */
val userResult = request.body.validate[User]
userResult.fold(
errors => {
    Future.successful(
    Result(
        header = ResponseHeader(400, Map(CONTENT_TYPE->"application/json")),
        body = Enumerator(Json.obj("status" ->"KO", "message" -> JsError.toFlatJson(errors)).toString.getBytes())
        ))
},
user => blocking{ 
  // `user` is an instance of the case class `models.User`
  val insertDate = new DateTime()
  val newUser = user.copy(created_at = Some(insertDate) )

  collection.insert(newUser).map { lastError => 
    Logger.debug(s"Successfully inserted with LastError: $lastError")
    val cursor = collection.find(newUser).cursor[User]

     // gather all the JsObjects in a list
val futureUsersList: Future[List[User]] = cursor.collect[List]()


// transform the list into a JsArray
val futureUsersJsonArray: Future[JsArray] = futureUsersList.map { persons =>
  Json.arr(persons)
}

// everything's ok! Let's reply with the array
val res = futureUsersJsonArray.map { persons =>

    Created(persons)
  } 
   Await.result(res, Duration(1000, MILLISECONDS))
}


}

) }

于 2014-10-24T01:20:05.907 回答
0

我也是新手,但是在响应式 mongo 0.11 中,他们删除了 LastError 结构以支持WriteResult。WriteResult 上确实有一个 originalDocument 字段,但不幸的是它设置为 None 并带有注释 'TODO'

我想出什么来返回创建的文档(减去 _id 字段),

  def promiseOfWriteResult[T](writeResult:Future[WriteResult])(value:T) = {
    val p = Promise[T]
    writeResult map {
      case ok if ok.ok   => p.success(value)
      case error         => p.failure(error.getCause)
    } recover { // !important
      case x : Throwable => p.failure(x)
    }
    p.future
  }

这将被用作,

promiseOfWriteResult(collection.insert(doc))(doc)
于 2015-08-25T19:16:11.920 回答