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. Используется шаблон метода расширения .
Не уверен, что это лучше, чем макросы в решении классов дел. У меня просто нет _t в моих документах.
Мне удалось придумать собственный кодек, использующий макросы и классы дел, а также пользовательский вызов codecRegistry, но он становился ужасно быстрым. Ужаснее, чем метод расширения расширения, показанный выше.
Это менее безопасный тип, чем решение для макросов, но работа выполняется быстрее, если не грязнее. Быстрее в том, что мне не нужно переписывать всю схему как case-классы.
На основе MongoDB Scala Driver version 2.6.0
Это, вероятно, должно быть сделано в правильном запросе на получение, но он, вероятно, будет отклонен по той или иной причине.