Reputation: 1761
Casbah has an expand function that lets you retrieve nested keys. Does the newer MongoDB Scala Driver have this functionality?
Upvotes: 2
Views: 263
Reputation: 4133
In Scala MongoDB driver you can use Macros to generate codecs from your case classes. Even you can create your codecs for you co-products (sealed trait). According to the doc: "Simple case classes and nested case classes are supported.". So take a look to the examples here
ReactiveMongo uses macros too, but there are another alternatives using Shapeless like: https://github.com/julienrf/reactivemongo-derived-codecs
Upvotes: 1
Reputation: 1761
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
}
}
This solution is more in spirit of the original expand function from Casbah. It uses the extension method pattern.
Not sure that it is better than the macros on case classes solution. I just didn't have _t in my documents.
I did manage to come up with a custom codec using the macros and case classes and a custom invocation of the codecRegistry, but it was getting ugly fast. Uglier than the expand extension method shown above.
This is less type safe than the macro solution but gets the job done quicker if not dirtier. Quicker in that I don't have to rewrite the entire schema as case classes.
Based on MongoDB Scala Driver version 2.6.0
This should probably be made into a proper pull request, but it'd probably get rejected for one reason or another.
Upvotes: 1