Class inheritance in MongoDB

1,272 views
Skip to first unread message

Kevin Stembridge

unread,
Dec 5, 2011, 6:44:01 PM12/5/11
to Lift
Hi all,
I'm trying to port an existing proof-of-concept written in Java, using
an RDBMS, to Lift using MongoDB. I've never used Lift, Scala or
MongoDB before so its quite a learning curve.

The issue I'm struggling with now is how to implement class
inheritance in MongoDB. In my Java domain model I have the following
classes:
Party
Organization extends Party
Person extends Party
User extends Person

I don't expect to have any trouble modelling these classes in Scala
but I don't know how to then map them to Collections and Documents in
MongoDB. I have seen a tutorial that describes how the C# driver
automatically handles the inheritance for you but there doesn't seem
to be any such functionality in the Java/Scala world.

The reason I'm posting this question in a Lift forum is because I
expect the eventual solution to have something to do with lift-mongodb-
record (at least I would like that to be the case).

Any pointers would be great.

Thanks,
Kevin

IL

unread,
Dec 6, 2011, 2:37:56 AM12/6/11
to lif...@googlegroups.com
lift-mongodb is based on lift-json for this kinda converting job.
So let's think about how to convert it to json.

It's enough for your needs.

Remember that lift-json only support scala case class(and other class with constructor contains all parameter need to be set. It set values by constructor but not setter method)

And I think the record api is not good for inheritance, so you should use lift-mongo or casbah to save and read your converted json objects.


Regards,

IL

Kevin

unread,
Dec 6, 2011, 9:12:52 AM12/6/11
to Lift

Kevin

unread,
Dec 6, 2011, 9:14:01 AM12/6/11
to Lift

Tim Nelson

unread,
Dec 6, 2011, 11:03:22 AM12/6/11
to Lift
Hi Kevin,

Inheritance with Record is a little tricky, but there are some things
you can do, as pointed out in the links in the posts above.

If you'd prefer to use regular case classes then I'd suggest using
Casbah/Salat. Lift has MongoDocument, but Casbah/Salat is more than
likely a better choice. If you go this route you'll lose all of the
features of Record though. In particular, validation and auto form
creation/LiftScreen.

Tim


On Dec 5, 5:44 pm, Kevin Stembridge <kevin.stembridge....@gmail.com>
wrote:

Kevin Stembridge

unread,
Jan 26, 2012, 4:25:29 PM1/26/12
to Lift
Thank you all for the advice. Looking at the samples in the suggested
links I realise that I don't know enough Scala to understand them. I
think I might have to focus a bit on the basics of the language
first.

On Dec 6 2011, 4:03 pm, Tim Nelson <t...@eltimn.com> wrote:
> Hi Kevin,
>
> Inheritance with Record is a little tricky, but there are some things
> you can do, as pointed out in the links in the posts above.
>
> If you'd prefer to use regular case classes then I'd suggest using
> Casbah/Salat. Lift has MongoDocument, but Casbah/Salat is more than
> likely a better choice. If you go this route you'll lose all of the
> features of Record though. In particular, validation and auto form
> creation/LiftScreen.
>
> Tim
>
> On Dec 5, 5:44 pm,Kevin Stembridge<kevin.stembridge....@gmail.com>

Kevin Stembridge

unread,
May 10, 2012, 4:27:57 PM5/10/12
to lif...@googlegroups.com
I've found some time to have another look at my options for mapping class hierarchies. I checked out Casbah/Salat. But I don't want to give up on Record just yet because of the extra features that come with it.

When you say its a little tricky, does that mean its impossible? I've been having a look at the implementation and I think there might be some things I can try. But my first hurdle is some basic scala stuff. I need to create my Record classes first of all but I'm getting errors that are related to type parameterization. I don't know enough Scala to figure out what I need to do to fix the problem. I'm hoping you guys can help.

Here are a couple of my classes:


class PartyRecord extends MongoRecord[PartyRecord] with UUIDPk[PartyRecord] {
  def meta = PartyRecord
  object name extends StringField(this, 128)
}
object PartyRecord extends PartyRecord with MongoMetaRecord[PartyRecord]


class OrganizationRecord extends PartyRecord {
  def meta = OrganizationRecord
}
object OrganizationRecord extends OrganizationRecord with MongoMetaRecord[OrganizationRecord]


OrganizationRecord doesn't compile because it expects the meta method to return a PartyRecord. So I believe I need to define PartyRecord so that it is parameterized with an upper bound of PartyRecord.
The class below is is the closest I've come so far to getting something that compiles but it complains that the value MyType cannot be found.

class PartyRecord[MyType <:PartyRecord[MyType]] extends MongoRecord[MyType] with UUIDPk[MyType] {
  self: MyType =>
  def meta = PartyRecord
  object name extends StringField(this, 128)
}
object PartyRecord extends PartyRecord[MyType] with MongoMetaRecord[PartyRecord[MyType]]


I'm hoping this is just a lack of understanding of how type parameterization works in Scala. Does anyone know what I need to do to get my type hierarchy to compile?

Cheers,
Kevin

Tim Nelson

unread,
May 11, 2012, 8:19:18 AM5/11/12
to lif...@googlegroups.com
Hi Kevin,

The problem has more to do with the relationship between MongoRecord and MongoMetaRecord than type hierarchy. I don't think you'll be able to do it the way you're trying here. What you can do is the following:

trait BaseRecord[OwnerType <: BaseRecord[OwnerType]] extends MongoRecord[OwnerType] with UUIDPk[OwnerType] {
  self: OwnerType =>

  object name extends StringField(self, 128)
}

class PartyRecord[OwnerType <: PartyRecord[OwnerType]] extends BaseRecord[OwnerType] {
  def meta = PartyRecord
}

object PartyRecord extends PartyRecord with MongoMetaRecord[PartyRecord]

class OrganizationRecord[OwnerType <: OrganizationRecord[OwnerType]] extends BaseRecord[OwnerType] {
  def meta = OrganizationRecord
}
object OrganizationRecord extends OrganizationRecord with MongoMetaRecord[OrganizationRecord]


Basically, you can't create a concrete MongoRecord class and then extend that. You can create a trait and extend that, however.

Tim

Kevin Stembridge

unread,
May 12, 2012, 1:38:39 PM5/12/12
to lif...@googlegroups.com
Hi Tim,
Thanks for the response.
I was hoping for better news though. My domain model requires concrete classes to extend other concrete classes. e.g. PartyRecord -> PersonRecord -> UserRecord.

I'm going to have to weigh up the trade-offs.

Thanks for the advice.
Kevin

Ben Phelan

unread,
May 14, 2012, 8:38:01 PM5/14/12
to lif...@googlegroups.com
Between traits, overriding collectionName, optional fields and Mongo's schemalessness you can go a long way - or make quite a mess - but it is a bit of a shame that the kind of thing you want isn't easier here.  There are lots of advantages to MongoRecord despite the inheritance thing.
Reply all
Reply to author
Forward
0 new messages