[英]Play: How to implement vermongo with ReactiveMongo
我想在MongoDB中更新JSON文档,如下所示:
{
"_id":{"$oid":"52dfc13ec20900c2093155cf"},
"email": "joe@domain.com",
"name": "joe",
"_version": 2
}
...并希望在每次更新时创建这样的vermongo文档:
{
"_id { "_id":{"$oid":"52dfc13ec20900c2093155cf"}, "_version": 1},
"email": "joe@domain.com",
"name": "joe",
"_version": 1,
"_timestamp" : "2014-02-02T00:11:45.542"
}
我尝试过这样的解决方案:
trait MyDao {
...
private val shadowCollection = ReactiveMongoPlugin.db.collection[JSONCollection](
collection.name + ".vermongo"
)
private def toVersioned(deleted: Boolean) = __.json.update(
(__ \ '_id).json.copyFrom((__ \ '_id \ '$oid).json.pickBranch) andThen
(__ \ '_id \ '_version).json.copyFrom((__ \ '_version).json.pick) andThen
// (__ \ '_version).json.put(if (deleted) JsString(s"deleted:$version") else JsNumber(version)) andThen
(__ \ '_timestamp).json.put(Json.toJson(LocalDateTime.now))
)
private def version(doc: JsValue, deleted: Boolean): Future[LastError] = {
shadowCollection.insert(doc.transform(toVersioned(deleted)).get)
}
}
toVersioned
方法有三个问题:
第1行:它不会创建多字段_id
第2行:当我尝试将_version
创建为_id
的第二个字段时崩溃
第3行:(注释掉)如果参数deleted
为true
,我想通过将"_version": 1
替换为"_version": "deleted:1"
来将文档标记为已"_version": "deleted:1"
; 我不清楚如何处理这里的情况。
很棒的问题; 我一直想要了解Play的JSON变换器多年,最后一个很好的情况来尝试它们。
我应该注意到,在添加了所有重要的functional.syntax._
import之前,我完全无法正常工作:
import play.api.libs.functional.syntax._
解决方案始于变压器页面上的Gizmo - > Gremlin变压器示例; 这就是我的使用and
与reduce
,从而彻底转换(原谅双关语),整个事情是如何工作的。
所以这里是:
private def toVersioned(deleted: Boolean) = (__.json.update(
( __ \ '_id ).json.copyFrom((__ \ '_id \ '$oid).json.pickBranch) and
( __ \ '_id \ '_version).json.copyFrom((__ \ '_version).json.pick) and
(__ \ '_version).json.update(
of[JsValue].map { case JsNumber(oldVersion) =>
if (deleted) JsString(s"deleted:$oldVersion") else JsNumber(oldVersion)
}
) and
(__ \ '_timestamp).json.put(Json.toJson(LocalDateTime.now)) reduce
)
andThen
( __ \ '_id \ '$oid ).json.prune
)
关键点:
我不能(在合理的时间内)在一个变换中实现_id
节点的“移动”,因此第一个传递将其“向下”复制一个级别,第二个传递(在andThen
)删除旧的$oid
。 几乎可以肯定的是......
使用and
似乎改变了copyFrom
的范围,允许_version
被正确地从顶级中挑选出来 - 当使用andThen
它似乎只有在下降到“目标”下方的节点时才起作用
我对这里deleted
的处理感到非常满意 - map
似乎既有Scala-也有PlayJSON-idiomatic。 Of[JsValue]
是必要的,因为我们在这里返回一个JsString
或一个JsNumber
,而JsValue
似乎是一个合适的超类
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.