Reactivemongo将地图序列化为BSONDocument

时间:2013-12-04 22:29:05

标签: mongodb scala reactivemongo

我将BSONDocumentWriter定义为将域对象(案例类)映射到要使用ReactiveMongo驱动程序在MongoDB中持久保存的BSON文档。定义编写器对于案例类来说非常简单(虽然繁琐且容易出错:我希望有类似Salat的解决方案)。但是,我似乎无法对Map[String,Any]执行相同的操作(其值可以是numeric,date或string类型)。我找到了一个code example来定义地图的通用编写器(和读者):

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)
  }
}

但是如果类型BSONDocumentWriter没有隐式V,那么这不起作用,即代码段:

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))
                          ^

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

我不确定为什么会这样,以及我如何解决它。也许我错过了一些明显的东西?想法?

1 个答案:

答案 0 :(得分:1)

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 Extensions