ReactiveMongo + Play 2:流式传输子文档(数组)

时间:2015-07-01 11:16:31

标签: mongodb scala stream playframework-2.3 reactivemongo

在以下示例中,我正在使用:

  • MongoDB(使用WiredTiger引擎的> 3.0)
  • 在Scala中播放框架2.3.8
  • org.reactivemongo:play2-reactivemongo:0.11.0.play23-M3

首先,假设我们在MongoDB集合中有以下文档,例如" urlColl":

{
  "_id" : ObjectId("5593bebe89645672000deec4"),
  "url" : "urlPath",
  "content" : [
      "a",
      "ab",
      "abc",
      "abcd"
  ]}

在Play中,只要将新文档插入" urlColl"就可以将新文档流式传输到客户端。集合,在Play中使用以下方法:

def feed = Action {
  val cursor = collection
    .find(BSONDocument(), BSONDocument("content" -> 1))
    .options(QueryOpts().tailable.awaitData)
    .cursor[List[Try[BSONValue]]](ReadPreference.nearest)

  val dataProducer = cursor.enumerate(Int.MaxValue).map(_.toString)
  Ok.chunked(dataProducer &> EventSource()).as("text/event-stream")
}

和隐含的读者:

implicit object ContentToList extends BSONDocumentReader[List[Try[BSONValue]]] {
    def read(doc: BSONDocument): List[Try[BSONValue]] = {
      doc.getAs[BSONArray]("content").get.stream.toList
    }
}

然后,每次一个带有"内容的新文件"插入数组后,它会自动发送到客户端。

我的问题很简单:

是否可以向客户端流式传输"内容"中注入的新数据?子阵列?

实际上,由于没有插入新文档(在现有文档的数组中插入了新值),因此光标中没有检测到任何内容,更不用说将任何内容发送给客户端。

提前谢谢!

@cchantep,回答你的上一条评论:

是的,我面临一些缓慢的疑问。事实上,我在一个用于推送数据的网页中有一个表单,另一个网页是服务器发送事件的。

验证第一页的形式最多可能需要3秒钟。 在Mongo日志中,我可以看到:

I QUERY    [conn329] getmore test.events cursorid:22982535122 ntoreturn:0 
keyUpdates:0 writeConflicts:0 numYields:0 nreturned:1 reslen:86 
locks:{ Global: { acquireCount: { r: 1000 } }, Database: { acquireCount: 
{ r: 1000 } }, Collection: { acquireCount: { r: 1000 } } } 2783ms. 

由于tailable游标,这是事件集合的日志(2783ms)。也许这可能导致问题?

编辑: 我已经禁用了tailable游标(coll.find(selector).options(QueryOpts()。tailable.awaitData))并且性能要好得多。你有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

最终release of 0.11.0可用"org.reactivemongo" %% "play2-reactivemongo" % "0.11.0.play23"

关于子数组,MongoDB中的tailable游标(不仅仅是ReactiveMongo)正在监视新的top-document。由于您的文档已更新以将元素添加到数组属性中,因此在创建光标流时已将其返回。

如果要实现事件源,最好在事件集合上而不是在实体集合(快照集合)上使用tailable游标。

您可以使用EventSource Play Mongo Knockout找到一个示例Play应用。