0

I'm currently playing around with reactivemongo and mongodb and I found something I do not know how to handle.

Let say I have an case class UserInfo:

case class UserInfo(override var _id: Option[BSONObjectID] = None,
                    firstName: String,
                    lastName: Option[String],
                    email: Option[String],
                    mobile: Option[String],
                    fbId: Option[String],
                    fbPublish: Option[Boolean]) {    
}

this object represent an user. The user has always a firstName and might have an email or mobile number.

object UserInfo {

  import play.modules.reactivemongo.json.BSONFormats._

  implicit val userInfoReads: Reads[UserInfo] = (
    (__ \ "_id").read[Option[BSONObjectID]] and
    (__ \ "firstName").read[String] and
      (__ \ "lastName").read[Option[String]] and
      (__ \ "email").read[Option[String]] and
      (__ \ "mobile").read[Option[String]] and
      (__ \ "fbId").read[Option[String]] and
      (__ \ "fbPublish").read[Option[Boolean]]
    )(UserInfo.apply _)

  implicit val userInfoWrites: Writes[UserInfo] = (
    (__ \ "_id").write[Option[BSONObjectID]] and
    (__ \ "firstName").write[String] and
      (__ \ "lastName").write[Option[String]] and
      (__ \ "email").write[Option[String]] and
      (__ \ "mobile").write[Option[String]] and
      (__ \ "fbId").write[Option[String]] and
      (__ \ "fbPublish").write[Option[Boolean]]
    )(unlift(UserInfo.unapply))    
}

In the UserInfo companion object I define the writes and reads for UserInfo. When inserting this document the UserInfo is saved to my Mongo instance and the fields that are None is saved as null. Since I have a lot of users I would like to set a index on firstName + email and a second index on firstName + mobile:

ensureIndex(List("firstName" -> IndexType.Ascending, "email"-> IndexType.Ascending), unique = true, sparse = true)
ensureIndex(List("firstName" -> IndexType.Ascending, "mobile"-> IndexType.Ascending), unique = true, sparse = true)

I insert an UserInfo with firstName and email. Rest of the fields are None.

And now comes the part I do not know how to handle. Since None writes to null the null value is saved in my collection of userinfos. I try to insert the same firstName and email, this should fail and it does, but for the wrong reason. The reason in my case is that there is an index created for jakob and null:

DB operation failed: [message=DatabaseException['E11000 duplicate key error index: userinfos.$userInfo.userInfo.mobile_1  dup key: { : "jakob", : null }' (code = 11000)]]

As I understand sparse only works for missing values and since null is a value, sparse do not work in this case. So how should I handle this? Is it possible to create indexes with values that could be null? Or should I treat my None values in some other way? Maybe I could change the writes so that if None write empty [T] param. What is the MongoDB way of handling this?

jakob
  • 5,979
  • 7
  • 64
  • 103
  • This has been answered....well many times if you google – Sammaye Nov 25 '13 at 22:41
  • How about you pointing me to that answer? – jakob Nov 26 '13 at 08:15
  • Found this: https://jira.mongodb.org/browse/SERVER-2193 Kind of old. But I guess that this means that mongodb still do not support sparse on compound indexes – jakob Nov 26 '13 at 08:43
  • Hmm it seems the google search result is filled with only how to search, weird that it doesn't pick up the questions I have answered on this, I will come up with something when I have a bit more time – Sammaye Nov 26 '13 at 09:46
  • Ha this is actually trickier than the title suggested. I would create a unique index on mobile and email (it seems as though there shouldn't be a duplicate of that) since those are really the only unique pieces of information. However having it compound like, though only one namespace and easier to load into memory might be larger than two separate indexes. I would definitely take off the fristname index though, not even sure if this would work with sparse indexes since sparse just omits null so if two documents have null email or mobile but the first name of jake... – Sammaye Nov 26 '13 at 12:27

0 Answers0