ReactiveMongo + Play 2:流式传输子文档(数组)
ReactiveMongo + Play 2: stream a sub document (array)
在下面的例子中,我使用的是:
- MongoDB(> 3.0 带 WiredTiger 引擎)
- 在 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")
}
和隐含的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)正在监视新的顶级文档。由于您的文档已更新以将元素添加到数组 属性,因此它在创建时已在游标流中返回。
如果要实现事件源,最好将可尾游标放在事件集合上而不是实体集合(快照集合)上。
您可以使用 EventSource
和 Play Mongo Knockout 找到示例 Play 应用。
在下面的例子中,我使用的是:
- MongoDB(> 3.0 带 WiredTiger 引擎)
- 在 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")
}
和隐含的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)正在监视新的顶级文档。由于您的文档已更新以将元素添加到数组 属性,因此它在创建时已在游标流中返回。
如果要实现事件源,最好将可尾游标放在事件集合上而不是实体集合(快照集合)上。
您可以使用 EventSource
和 Play Mongo Knockout 找到示例 Play 应用。