3

I'm using reactivemongo.

While reading document from mongodb I have written code specific to the structure.

Structure

{
  "name" : "test",
  "age" : 3
}

For reading this I am using code like :

val cursor = collection.find(query).cursor[BSONDocument]
cursor.enumerate.apply(Iteratee.foreach { doc =>
  var name: BSONDocument = doc.getAs[String]("name").get
  var age: BSONDocument = doc.getAs[Int]("age").get
}

So now if later on, BSON structure gets changed like:

{
  "name" : {
    firstName : "fname",
    lastName : "lname"
  },
  "age" : 3
}

So now I have to change my code for reading it

val cursor = collection.find(query).cursor[BSONDocument]
cursor.enumerate.apply(Iteratee.foreach { doc =>
  var name: BSONDocument = doc.getAs[BSONDocument]("name").get
  var fname : String  = name.getAs[String]("firstName").get
  var lname : String  = name.getAs[String]("lastName").get
  var age: BSONDocument = doc.getAs[Int]("age").get
}

I want to keep the data, which is currently using the old structure (i.e "name" as string) and insert new data using the new structure (i.e "name" as BSONDocument).

While reading document with old structure an exception "None.get" is thrown, because as per the read method "name" should be a BSONDocument.

What should be my approach to handle this issue??

tmbo
  • 1,317
  • 10
  • 26
Nitin
  • 57
  • 7

1 Answers1

1

This is a typical migration issue. And there are several ways to deal with migration. Typical solutions are:

  1. Migrate all existing documents in the database to fit your new format (either using the mongo shell, scripts or you can even include it in your application on startup.). There is currently no "auto migration" plugin for mongo available that does the job for you (I am working on one, but it is not yet finished).

  2. Make your application code aware of different schema versions. This means writing your BSONDocument parsing logic in a way that it accepts both versions.

tmbo
  • 1,317
  • 10
  • 26
  • Isn't MongoDB schemaless (http://blog.mongodb.org/post/119945109/why-schemaless)? I just switched from Ruby, and there it was possible to read/write any fields irrespectively of fields. Is there any reason ReactiveMongo uses such approach? – Mike Bevz Feb 04 '14 at 10:14
  • You are right, mongo doesn't enforce a schema on a collection. But to avoid dealing with bson/json objects when implementing business logic ReactiveMongo allows to parse bson objects into classes. Since classes aren't that flexible most of the time, one still is somewhat bound to a schema. – tmbo Feb 04 '14 at 12:11
  • For now I had to implement a set of methods that check whether getAs throws an exception. Is it possible in Scala to return some equivalent of nil in Ruby, which would substitute any type? – Mike Bevz Feb 04 '14 at 15:36
  • What are you actually trying to accomplish? Can you drop me some code or example? Sure you could use ".getAs[String]("test").getOrElse(null)". (but you WILL definitely go to hell for doing so, as this will lead to NullPointer exceptions in your code one day or another). – tmbo Feb 05 '14 at 04:25