2013-05-22 14 views
0

我正在嘗試在我的play2應用程序中將一些嵌套調用與reactivemongo結合起來。 我收到從createObjects返回的對象列表。我然後循環就過去了,檢查對象的集合中存在,如果不將其插入:我應該如何構建我的play2應用程序中嵌套的reactivemongo調用?

def dostuff() = Action { 
    implicit request => 
     form.bindFromRequest.fold(
     errors => BadRequest(views.html.invite(errors)), 
     form => { 
     val objectsReadyForSave = createObjects(form.companyId, form.companyName, sms_pattern.findAllIn(form.phoneNumbers).toSet) 
      Async { 
      for(object <- objectsReadyForSave) { 
       collection.find(BSONDocument("cId" -> object.get.cId,"userId" -> 
       object.userId.get)).cursor.headOption.map { maybeFound => 
       maybeFound.map { found => 
        Logger.info("Found record, do not insert") 
       } getOrElse { 
        collection.insert(object) 
       } 
       } 
      } 
      Future(Ok(views.html.invite(form))) 
      }    
      }) 
    } 

我覺得這樣也沒有那麼好,因爲它可以,感覺不是「play2」和「reactivemongo」 。 所以我的問題是:我應該如何構建我的嵌套調用來獲得我想要的結果 並獲取已插入哪些對象的信息?

回答

2

我不是在mongoDB中的專家,也不是在ReactiveMongo中,但似乎您嘗試使用NoSQL數據庫的方式與您使用標準SQL數據庫的方式相同。請注意,mongoDB是異步的,這意味着操作可能會在將來執行,這就是爲什麼插入/更新操作不返回受影響的文檔。關於你的問題:

1要插入的對象,如果它們不存在,並獲得已插入了哪些對象的信息?

你或許應該看看MongoDB的db.collection.update()方法,並與upsert參數爲真調用它。如果你可以負擔得起,它將更新文件,如果它們已經存在於數據庫中或否則插入它們。此操作不會返回受影響的文檔,但您可以通過訪問last error來檢查有多少文檔受到影響。見reactivemongo.api.collections.GenericCollection#update,返回Future[LastError]

2對於所有插入的對象,將它們添加到列表中,然後使用Ok()調用返回它。

再次插入/更新的文件將不會被返回。如果您確實需要返回完整的受影響文檔,則需要進行另一個查詢以檢索匹配的文檔。

我可能會重寫代碼這種方式(沒有錯誤/故障處理):

def dostuff() = Action { 
    implicit request => 
     form.bindFromRequest.fold(
      errors => BadRequest(views.html.invite(errors)), 
      form => { 
       val objectsReadyForSave = createObjects(form.companyId, form.companyName, sms_pattern.findAllIn(form.phoneNumbers).toSet) 
       Async { 
        val operations = for { 
         data <- objectsReadyForSave 
        } yield collection.update(BSONDocument("cId" -> data.cId.get, "userId" -> data.userId.get), data, upsert = true) 

        Future.sequence(operations).map { 
         lastErrors => 
          Ok("Documents probably inserted/updated!") 
        } 
       } 
      } 
     ) 
} 

參見斯卡拉期貨:http://docs.scala-lang.org/overviews/core/futures.html

這是非常有用的! ;)

+0

很好的回答!這正是我期待的! – jakob

2

下面是我如何重寫它。

def dostuff() = Action { implicit request => 
    form.bindFromRequest.fold(
    errors => BadRequest(views.html.invite(errors)), 
    form => { 
     createObjects(form.companyId, 
     form.companyName, 
     sms_pattern.findAllIn(form.phoneNumbers).toSet).map(ƒ) 

     Ok(views.html.invite(form)) 
    } 
) 
} 

// ... 
// In the model 
// ... 

def ƒ(cId: Option[String], userId: Option[String], logger: Logger) = { 
    // You need to handle the case where obj.cId or obj.userId are None 
    collection.find(BSONDocument("cId" -> obj.cId.get, "userId" -> obj.userId.get)) 
    .cursor 
    .headOption 
    .map { maybeFound => 
     maybeFound map { _ => 
     logger.info("Record found, do not insert") 
     } getOrElse { 
     collection.insert(obj) 
     } 
    } 
} 

可能有一些語法錯誤,但這個想法是存在的。

+0

謝謝你的回答!如果我不在模型中處理這個事情,請創建一個方法def dostuff(object:MyObject)= {}並調用.map(dostuff)來代替? – jakob

+0

這意味着你將會在你的模型中處理表單內容,這很麻煩。 –

+0

我明白了,但是如果你看看響應式mongo例子,他們通常會在模型中處理表單內容。 https://github.com/sgodbillon/reactivemongo-demo-app/blob/master/app/models/articles.scala。也許如果我可以和你聊聊整個使用案例,會更容易理解? – jakob

相關問題