Change Primary key type or index doc fields

13 views
Skip to first unread message

Pat Ferrel

unread,
May 7, 2017, 8:18:08 AM5/7/17
to scala-salat
I'd like to find objects in a SalatDAO by an id that might be a Map key. For instance

case class (id: String, more stuff...)

The id will be unique in the collection but not globally. How should I handle this, the Mongo docs talk about ObjectIDs but these seem of limited external use (outside Mongo itself). The Salat annotations do not seem to cover this except that I can declare 

case class ( @Key("_id") id: String, more stuff ...) but my reading of this is that is just renames "id" as "_id" in the database. The Strings will be unique for the collection, but again, not for the entire DB. Is this ok? Will these Strings be indexed? Should I just create:

case class ( someId: String, more stuff ...) in which case what annotation tells Mongo to index someId?

Also the SalatDAO has a someDAO.findById but it seems to require an int and so is not very helpful in this case. Is it fast/efficient to use a key that is a string?

Thanks

Noah Zucker

unread,
May 7, 2017, 9:38:56 AM5/7/17
to scala-salat
Hello - see:

https://groups.google.com/d/msg/scala-salat/C0pJBxKEReA/CCJxEum0xOoJ


The primary key in any Mongo collection is the "_id" field.  The type of the _id field is often an ObjectId but could be any type you choose. 

If you want the String field of your case class to be unique in the database (i.e. indexed with a unique constraint), you'll need to write a little bit of vanilla Mongo code to do this. You can do it in your Scala application using Casbah. Salat doesn't do that automatically when you define the DAO.

Pat Ferrel

unread,
May 7, 2017, 10:48:54 AM5/7/17
to scala-salat
Let me see if U have this right, I define my DAO like this:

  object GroupsDAO extends SalatDAO[GroupParams, String](collection = MongoConnection()(resourceId)("groups"))

and GroupParams ike this:

case class GroupParams (
  @Key("_id") id: String,
  //groupId: String,
  ...


So now I get `findById` that wants a string. So it all looks good but I need to define the index on the collection in separate Casbah code before I create the DAO with `MongoConnection()(resourceId)("groups"))` ?

It seems like the DAO could do this given an extension of the @Key annotation and I thought it was until I read the docs more carefully. The @Key is more like a hypothetical @Rename.

Pat Ferrel

unread,
May 7, 2017, 12:36:17 PM5/7/17
to scala-salat
I don't understand the scaladocs for createIndex, nor the terminology in the Mongo docs. There are so many optional ways to use createIndex that this simple case escapes me and there are no examples for it in the Casbah docs. I've posted this question on the Casbah group too.

How do I create the index on a collection of GroupParams as defined below with  _id: String? I don't care about sort order and the id will be unique.


BTW below I meant "if I have this right" :-)

Noah Zucker

unread,
May 7, 2017, 1:20:37 PM5/7/17
to scala-salat
This is a big topic and - while I have used and developed Salat - I don't claim to have deep Mongo expertise, I'll provide my thoughts on this as a starting point.

Salat isn't (nor does it strive to be) a full-featured ORM library - like, for example, Hibernate, which sets up DB schema and relational integrity constraints from annotations.  Salat doesn't do that. What it does do is provide simple case-class (and case object) serialization to Mongo.  Otherwise, many of it's "DAO" function calls delegate directly to the underlying Casbah library, but with the boilerplate of the Grater serialization calls handled for you.

As you mentioned, the @Key annotation is really just a "rename" or "alias" annotation. It does not define the primary key of the case class. However, because many pre-existing Scala case classes do NOT have a field named "_id" the @Key annotation is useful for making the translation between your database document (with _id) and your case class (with groupId) seamless.

But what about the fact that groupId is not an ObjectId? The Mongo documentation has a bit to say about this. I would recommend starting there, and posting follow up questions in the Mongo lists / support / StackOverflow.  This is a general problem not specific to Salat.
https://docs.mongodb.com/manual/core/document/

One additional thing I would add: you might consider having an intermediary "holder" case class that is exactly like your domain object / record case class, save that it has an _id: ObjectId. There's nothing stopping you from having your document collection having two indexes: the automatic one for _id, and a second one (also with a unique constraint) for the groupId: String field. Of course, you would not use DAO.findById to look up records by their groupId.  You would use the normal find() or findOne() methods. 

So you might have
case class ThingHolder(_id: ObjectId, thing: Thing)

That's up to you, of course. Some people don't like the "noise" of having two ID fields (the "auto" one and the natural one from the data). It depends on factors outside the scope of this question.

Hope this helps!

Pat Ferrel

unread,
May 8, 2017, 4:57:52 PM5/8/17
to scala-salat
From the Casbah list, I do nothing but name the field _id: String and Mongo will auto index it as the primary key and a String to boot--woohoo. This is why I love Mongo. Yes. I'm aware of the great methods for creating complex indices with custom sort orders and all that, very helpful in other projects. I was just asking a new question about the primary key.

In the course of the answer he mentioned the "newer MongoDB Scala driver" which uses async idioms. Is Casbah deprecated? Will Salat eventually work with the newer driver?

BTW ORMs are an anti-pattern, look it up ;-) But I love a nice simple DAO. I also love Scala async idioms.

Thanks again!

Pat Ferrel

unread,
May 8, 2017, 5:01:49 PM5/8/17
to scala-salat
FWIW: Also from the Casbah list, no not a replacement but uses the most recent async patterns built into the new Java driver. 

Noah Zucker

unread,
May 8, 2017, 5:04:37 PM5/8/17
to scala-salat
No problem!

Salat is currently a community-supported project with no commercial sponsor (read: paid developers). I'm more of "steward" than "lead developer" so I don't have any plans to do major work on Salat such as update it for the async driver.  Mostly we're trying to keep things up to date for the installed users / projects that have dependencies on Salat and know that it's often easier to patch small bugs / features than migrate.

Of course, if someone / some company wanted to start making contributions to Salat / add async driver support, we wouldn't be averse to that ;-)

Regards,
Reply all
Reply to author
Forward
0 new messages