0

My mongoDb collection looks like this:

> db.FakeCollection.find().pretty()
{
    "_id" : ObjectId("52b2d71c5c197846fd3a2737"),
    "categories" : [
            {
                    "categoryname" : "entertainment",
                    "categoryId" : "d3ffca550ae44904aedf77cdcbd31d7a",
                    "displayname" : "Entertainment",
                    "subcategories" : [
                            {
                                    "subcategoryname" : "games",
                                    "subcategoryId" : "ff3d0cbeb0eb4960b11b47d7fc64991b",
                                    "displayname" : "Games"
                            }
                    ]
            }
    ]
   }

I want to write a test case for the below collection using Specs2 JsonMatchers in scala with MongodbCasbah. How do I convert DBObjects to Strings?

sagar
  • 143
  • 1
  • 2
  • 11

2 Answers2

2

I believe your approach is slightly wrong here. Your collection should look like:

class Category extends BsonRecord[Category] {
  def meta = Category
  object categoryname extends StringField(this, 200)
  object categoryId extends StringField(this, 64)
  object displayname extends StringField(this, 100)
  object subcategories extends BsonRecordListField(this, Category)
}
object Category extends Category with BsonMetaRecord[Category] {
}

class FakeCollection extends MongoRecord[FakeCollection] with ObjectIdPk[FakeCollection] {
  def meta = FakeCollection
  object categories extends BsonRecordListField(this, Category)
}
object FakeCollection extends FakeCollection with MongoMetaRecord[FakeCollection] {
  override def collectionName = "fakecollection"
  def getEntryByName: List[Category] = {
    FakeCollection.find
  }
}

With that method you can do:

import net.liftweb.json.JsonAST.JValue;
import net.liftweb.http.js.JsExp;
import net.liftweb.http.js.JsExp._;
import net.liftweb.json.JsonDSL.seq2jvalue
val json: JsExp = seq2JValue(FakeColleciton.find.map(_.asJValue))
val stringContent = json.toJsCmd; // now it's here, you can match.

Have a look HERE, see how you can add Foursquare Rogue to make your life easier.

flavian
  • 28,161
  • 11
  • 65
  • 105
  • we are not using Lift Record we are using MongoDB Casbah – sagar Dec 20 '13 at 05:08
  • 2
    I also prefer Rogue whenever I deal with a stable and known schema. They have very type safe way to query DB. However, in one of my projects I had to use casbah and construct documents with arbitrary fields and make arbitrary queries. For these sorts of things Rogue + Record just don't fit. This is more of an exceptional case for me though. – yǝsʞǝla Jan 18 '14 at 22:18
  • @AlekseyIzmailov: I apologize for the plug, but does that mean Rogue+Record is also not well suited for a changing schema? – Erik Kaplun Feb 13 '14 at 20:56
  • @ErikAllik I think the whole point of using Record is to have typesafe way of accessing schema and the only way it can be achieved is by not having lots of variance in schema. You can still have optional fields but the purpose might get defeated quite fast in that case. If you change your schema a lot then its fine as long as you perform data migrations, but if your documents in a single collection have no common schema or it changes during runtime then Rogue is not very suitable. – yǝsʞǝla Feb 13 '14 at 21:33
  • I was thinking of doing on the fly/incremental schema migrations while using Rogue, but I guess I'll have to stick with migrations then. Or just adapt my Rogue schema accordingly. – Erik Kaplun Feb 13 '14 at 21:56
  • @ErikAllik I think on the fly migrations are fine as well as bulk migrations. I mean as long as most of the fields match your Record schema and your Record schema represents the latest version, not the other way around it should be fine. – yǝsʞǝla Feb 14 '14 at 00:16
1

Short answer:

val doc: com.mongodb.DBObject = ???
pretty(render(net.liftweb.mongodb.JObjectParser.serialize(doc)))

Long answer that explains what's going on. I included full type names for clarity:

import net.liftweb.mongodb.JObjectParser
import net.liftweb.json.DefaultFormats

// default JSON formats for `parse` and `serialize` below
implicit val formats = DefaultFormats

// Convert DBObject to JValue:
val doc: com.mongodb.DBObject = ??? // get it somehow
val jsonDoc: net.liftweb.json.JValue = JObjectParser.serialize(doc)

// Convert JValue to DBObject:
val doc2: net.liftweb.json.JObject = ???
val dbObj: com.mongodb.DBObject = JObjectParser.parse(doc2)

// Render JSON as String:
import net.liftweb.json._
pretty(render(jsonDoc))
// or use compactRender, compact(render(jsonDoc)), etc

To compare JSON docs there is Diff: val Diff(changed, added, deleted) = json1 diff json2.

More info here: https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/.

You can test with specs2 and Lift Diff this way for example:

json1 diff json2 mustEqual Diff(changedJson, addedJson, JNothing)
yǝsʞǝla
  • 16,272
  • 2
  • 44
  • 65