Reactivemongo将地图序列化为BSONDocument [英] Reactivemongo serializing a map into a BSONDocument

查看:45
本文介绍了Reactivemongo将地图序列化为BSONDocument的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义了BSONDocumentWriter,以使用ReactiveMongo驱动程序将域对象(案例类)映射到要保留在MongoDB中的BSON文档.为案例类别定义作者非常简单(尽管乏味且容易出错:我希望有类似Salat的解决方案).但是,我似乎无法对Map[String,Any](值可以是数字,日期或字符串类型)执行相同的操作.我找到了代码示例,它定义了通用编写器(和读者)以获取地图:

implicit def MapWriter[V](implicit vw: BSONDocumentWriter[V]): BSONDocumentWriter[Map[String, V]] = 
  new BSONDocumentWriter[Map[String, V]] {
  def write(map: Map[String, V]): BSONDocument = {
    val elements = map.toStream.map { tuple =>
      tuple._1 -> vw.write(tuple._2)
    }
    BSONDocument(elements)
  }
}

,但是如果没有V类型的隐式BSONDocumentWriter,即代码段,则此方法无效:

BSONDocument(
  "_id" -> "asd",
  "map" -> MapWriter[Any].write(Map("x" -> 1, "y" -> "2"))
)

无法编译:

could not find implicit value for parameter vw: reactivemongo.bson.BSONDocumentWriter[Any]
    "map" -> MapWriter[Any].write(Map("x" -> 1, "y" -> "2"))
                      ^

我认为也许作者应该写BSONValue而不是BSONDocument,所以我将示例修改如下:

implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, BSONValue]): BSONDocumentWriter[Map[String, V]] = 
  new BSONDocumentWriter[Map[String, V]] {
  def write(map: Map[String, V]): BSONDocument = {
    val elements = map.toStream.map {
      tuple =>
        tuple._1 -> vw.write(tuple._2)
    }
    BSONDocument(elements)
  }
}

为了简单起见,我尝试使用Int作为值类型,但还是使用代码段:

BSONDocument(
  "_id" -> "asd",
  "map" -> ValueMapWriter[Int].write(Map("x" -> 1, "y" -> 2))
)

无法编译:

could not find implicit value for parameter vw: reactivemongo.bson.BSONWriter[Int,reactivemongo.bson.BSONValue]
    "map" -> ValueMapWriter[Int].write(Map("x" -> 1, "y" -> 2))
                          ^

如果上述方法可行,我可以使用一些基类作为值类型并定义其隐式编写器.

我不确定为什么会这样以及如何解决.也许我缺少明显的东西?想法?

解决方案

ValueMapWriter 定义中 BSONValue 的通用类型参数边界不正确.如果您更改了行

implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, BSONValue]): BSONDocumentWriter[Map[String, V]] =

implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, _ <: BSONValue]): BSONDocumentWriter[Map[String, V]] =

然后它应该解析Int的隐式编写器.

BTW simple-reactivemongo 已经做到了.而且我还计划将此功能添加到 ReactiveMongo扩展.

I defined BSONDocumentWriters to map domain objects (case classes) to BSON documents to be persisted in MongoDB using the ReactiveMongo driver. Defining the writers is quite straight-forward for case classes (although tedious and error prone: I wish there was a Salat-like solution for that). However, I can't seem to be able to do the same for a Map[String,Any] (where the values can be of type numeric, date or string). I found a code example that defines a generic writer (and reader) for a map:

implicit def MapWriter[V](implicit vw: BSONDocumentWriter[V]): BSONDocumentWriter[Map[String, V]] = 
  new BSONDocumentWriter[Map[String, V]] {
  def write(map: Map[String, V]): BSONDocument = {
    val elements = map.toStream.map { tuple =>
      tuple._1 -> vw.write(tuple._2)
    }
    BSONDocument(elements)
  }
}

but this does not work if there's no implicit BSONDocumentWriter for the type V, i.e., the snippet:

BSONDocument(
  "_id" -> "asd",
  "map" -> MapWriter[Any].write(Map("x" -> 1, "y" -> "2"))
)

does not compile:

could not find implicit value for parameter vw: reactivemongo.bson.BSONDocumentWriter[Any]
    "map" -> MapWriter[Any].write(Map("x" -> 1, "y" -> "2"))
                      ^

I thought maybe the writer should write to a BSONValue instead of a BSONDocument so I modified the example as follows:

implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, BSONValue]): BSONDocumentWriter[Map[String, V]] = 
  new BSONDocumentWriter[Map[String, V]] {
  def write(map: Map[String, V]): BSONDocument = {
    val elements = map.toStream.map {
      tuple =>
        tuple._1 -> vw.write(tuple._2)
    }
    BSONDocument(elements)
  }
}

And to keep things simple, I tried to use Int as the value type but again, the snippet:

BSONDocument(
  "_id" -> "asd",
  "map" -> ValueMapWriter[Int].write(Map("x" -> 1, "y" -> 2))
)

does not compile:

could not find implicit value for parameter vw: reactivemongo.bson.BSONWriter[Int,reactivemongo.bson.BSONValue]
    "map" -> ValueMapWriter[Int].write(Map("x" -> 1, "y" -> 2))
                          ^

If the above had worked I could have used some base class as the value type and defined its implicit writer.

I am not sure why this is happening and how I can solve it. Maybe I am missing something obvious? Ideas?

解决方案

The generic type parameter boundary for BSONValue in ValueMapWriter definition is not correct. If you change the line

implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, BSONValue]): BSONDocumentWriter[Map[String, V]] =

with

implicit def ValueMapWriter[V](implicit vw: BSONWriter[V, _ <: BSONValue]): BSONDocumentWriter[Map[String, V]] =

then it should resolve the implicit writer for Int.

BTW simple-reactivemongo already does this. And I am also planning to add this functionality to ReactiveMongo Extensions.

这篇关于Reactivemongo将地图序列化为BSONDocument的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆