tolmach
tolmach

Reputation: 11

Mongodb scala driver codec for trait and inherited classes

Using the following mongo-driver. I want to insert and get structures (see below) from MongoDB.

 trait A {
   def id: ObjectId
 }

 case class B(id: ObjectId) extends A

 case class C(id: ObjectId, name: String) extends A

I find a solution with using sealed classes, but I want to use traits. I want to find a solution with Codecs or something else.

Upvotes: 1

Views: 1319

Answers (2)

Aki
Aki

Reputation: 1754

Since release 2.7, the mongodriver is now able to serialize sealed traits.
It works exactly like serializing a sealed classes.

Upvotes: 0

I had the same concern just a few days ago but didn't find anything in the documentation regarding sealed traits for modeling ADT in MongoDB.

In the end, I used sealed class as suggested in the official scala driver github repo.

If you really want to use traits (due to the definition of abstract methods) you can do something like this:

package example.model

import example.model.adt._
import org.mongodb.scala.bson.ObjectId
import org.mongodb.scala.bson.codecs.Macros._
import org.mongodb.scala.bson.codecs.DEFAULT_CODEC_REGISTRY
import org.bson.codecs.configuration.CodecRegistries.{fromProviders, fromRegistries}

trait MongoModel {
  def _id: ObjectId
}

object MongoModel {
  val codecRegistery = fromRegisteries(fromProviders(classOf[A]), DEFAULT_CODEC_REGISTRY)
}

Now you can have your ADT for A defined with sealed class.

package example.model.adt

import example.model.MongoModel
import org.mongodb.scala.bson.ObjectId

sealed class A

final case class B(_id: ObjectId) extends A with MongoModel
final case class C(_id: ObjectId) extends A with MongoModel

This answer doesn't solve the question directly but provides a feasible workaround. Note that this code is just an example. For a more complete implementation, you can see this github repo.

Upvotes: 4

Related Questions