【发布时间】:2019-05-28 13:27:31
【问题描述】:
Casbah 有一个expand 函数,可让您检索嵌套键。 较新的MongoDB Scala Driver 有这个功能吗?
【问题讨论】:
Casbah 有一个expand 函数,可让您检索嵌套键。 较新的MongoDB Scala Driver 有这个功能吗?
【问题讨论】:
package org.mongodb.scala.bson
import org.mongodb.scala.bson.DefaultHelper.DefaultsTo
import scala.reflect.ClassTag
import scala.util.Try
import scala.collection.JavaConverters._
object Expandable {
implicit class AddExpand(val underlying: Document) extends AnyVal {
def expand[TResult <: BsonValue: ClassTag](key: String)(implicit e: TResult DefaultsTo BsonValue): Either[Throwable, TResult] = {
val path = key.split('.')
path.init.tail
.foldLeft(Try(underlying.underlying.get(path.head).asDocument()).toEither){
case (parent, pathEl) => parent.flatMap(p => get[BsonDocument](p, pathEl))
}
.flatMap(p => get[TResult](p, path.last))
}
}
def get[TResult <: BsonValue](parent: BsonDocument, key: String)(implicit e: TResult DefaultsTo BsonValue, ct: ClassTag[TResult]): Either[Throwable, TResult] = {
Try(parent.asScala.get(key).map(ct.runtimeClass.cast).map(_.asInstanceOf[TResult]).getOrElse(throw new NoSuchElementException(key))).toEither
}
}
此解决方案更符合 Casbah 的原始扩展功能。它使用extension method pattern。
不确定它是否比案例类解决方案中的宏更好。我只是在我的文档中没有 _t。
我确实设法使用宏和案例类以及对 codecRegistry 的自定义调用提出了一个自定义编解码器,但它变得越来越难看。比上面显示的扩展扩展方法更丑。
这比宏解决方案的类型安全性差,但如果不是更脏的话,它可以更快地完成工作。更快,因为我不必将整个架构重写为案例类。
基于MongoDB Scala Driver version 2.6.0
这可能应该成为一个适当的拉取请求,但它可能会因为某种原因被拒绝。
【讨论】:
在 Scala MongoDB 驱动程序中,您可以使用宏从您的案例类生成编解码器。甚至您也可以为您的联产品创建编解码器(sealed trait)。根据文档:“支持简单案例类和嵌套案例类。”。所以看看例子here
ReactiveMongo 也使用宏,但还有其他使用 Shapeless 的替代方案,例如:https://github.com/julienrf/reactivemongo-derived-codecs
【讨论】: