0

I think there should be an easy solution around, but I wasn't able to find it.

I start accessing data from MongoDB with the following in Scala:

val search = MongoDBObject("_id" -> new ObjectId("xxx"))
val fields = MongoDBObject("community.member.name" -> 1, "community.member.age" -> 1)

for (res <- mongoColl.find(search, fields)) {
    var memberInfo = res.getAs[BasicDBObject]("community").get
    println(memberInfo)
}

and get a BasicDBObject as result:

{
"member" : [
    {
        "name" : "John Doe",
        "age" : "32",
    },{
        "name" : "Jane Doe",
        "age" : "29",
    },
    ...
]
}

I know that I can access values with getAs[String], though this is not working here... Anyone has an idea? Searching for a solution for several hours...

Max Leeds
  • 15
  • 4

4 Answers4

2

If you working with complex MongoDB objects, you can use Salat, which provides simple case class serialization.
Sample with your data:

case class Community(members:Seq[Member], _id: ObjectId = new ObjectId)

case class Member(name:String, age:Int)

val mongoColl: MongoCollection = _

val dao = new SalatDAO[Community, ObjectId](mongoColl) {}

val community = Community(Seq(Member("John Doe", 32), Member("Jane Doe", 29)))
dao.save(community)

for {
    c <- dao.findOneById(community._id)
    m <- c.members
} println("%s (%s)" format (m.name, m.age))
Sergey Passichenko
  • 6,920
  • 1
  • 28
  • 29
  • Sounds interesting. Could you provide a short example adressing deeper nested data? – Max Leeds Mar 15 '13 at 09:12
  • This looks very promising and clearly structured. In the long term I will go for it. But to solve my urgent problem the answer from anoopelias is short and fine. I would like to upvote your post but I have to get some reputation first... will make a task for that later on! :-) Thanks again! – Max Leeds Mar 15 '13 at 13:23
0

I think you should try

val member = memberInfo.as[MongoDBList]("member").as[BasicDBObject](0)
println(member("name"))
anoopelias
  • 9,240
  • 7
  • 26
  • 39
  • I am suspecting there is a less verbose solution. You can try `memberInfo.as[MongoDBList]("member").as(0)` and see if it can infer the type. – anoopelias Mar 16 '13 at 09:33
  • Also yes, salat is they way to go in the long run. It is an elegant wrapper over casbah. – anoopelias Mar 16 '13 at 09:36
0

This problem has not to do really with MongoDB, but rather with your data structure. Your JSON/BSON data structure includes

  • An object community, which includes
    • An array of members
      • Each member has properties name or age.

Your problem is completely equivalent to the following:

case class Community(members:List[Member])

case class Member(name:String, age:Int)

val a = List(member1,member2)

// a.name does not compile, name is a property defined on a member, not on the list
Edmondo
  • 19,559
  • 13
  • 62
  • 115
0

Yes, you can do this beautifully with comprehensions. You could do the following:

for { record <- mongoColl.find(search,fields).toList
      community <- record.getAs[MongoDBObject]("community")
      member <- record.getAs[MongoDBObject]("member")
      name <- member.getAs[String]("name") } yield name

This would work just to get the name. To get multiple values, I think you would do:

for { record <- mongoColl.find(search,fields).toList
      community <- record.getAs[MongoDBObject]("community")
      member <- record.getAs[MongoDBObject]("member")
      field <- List("name","age") } yield member.get(field).toString
Luciano
  • 2,388
  • 1
  • 22
  • 33