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

ReactiveMongo + Play 2: stream a sub document (array)

在下面的例子中,我使用的是:

首先,假设我们在 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")
}

和隐含的reader:

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

然后,每次插入带有"content"数组的新文档时,都会自动发送给客户端。

我的问题很简单:

是否可以将注入到 "content" 子数组中的新数据流式传输到客户端?

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

提前致谢!


@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)) 并且性能要好得多。你有什么想法吗?

谢谢!

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

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

如果要实现事件源,最好将可尾游标放在事件集合上而不是实体集合(快照集合)上。

您可以使用 EventSourcePlay Mongo Knockout 找到示例 Play 应用。