Adding data no primitives to MongoListField

43 views
Skip to first unread message

Nataly Nanda Huanca Patzi

unread,
Mar 5, 2015, 2:00:49 PM3/5/15
to lif...@googlegroups.com
Hi to all.

I have a doubt, in many sites I readed that in MongoListField we cannot add data no primitives like String, Int, etc. But before I know about this, I put in a MongoListField other objects and works fine.

I create a little  project for show this.

https://github.com/natalynanda/inheritance

 I have one class Shape, it is a Trait, and three concrete classes: Square, Triangle and Circle, One ShapeCollection class with a listShapes of type MongoListField[
Shapecollection, Shape[_]], many persons said me that it not will work fine, because this list will be saved like a string not like a objects, and it will be complicated for me for access to their attributes. But I can access fine, I put a test with this feature, the test run fine.
Some one can said me if it is a bug in MongoListField? or if after I will have problems with this declaration, how can I fix it, if it is necesary?

Torsten Uhlmann

unread,
Mar 6, 2015, 1:50:13 AM3/6/15
to lif...@googlegroups.com
Hi Nataly,

welcome to the Lift list!

MongoListField can be used only with basic types. Please see here for a discussion: https://groups.google.com/forum/#!searchin/liftweb/MongoListField/liftweb/OlrkIrWIj58/rubTCmba7gAJ

The alternatives would be MongoCaseClassListField or BsonRecordListField.

In our projects we use MongoListField to store primitives like String and Int, and BsonRecordListField to create embedded records.

Also, if you are using Foursquare's Rogue to query your database it does work well with them, i.e. if you want to query on data contained within an embedded record.

Does that help?

Torsten.

Nataly Nanda Huanca Patzi

unread,
Mar 6, 2015, 9:06:46 AM3/6/15
to lif...@googlegroups.com

Hi Torsten, thank you so much.

I have a trouble. This is the change that I did.

class ShapeType private() extends MongoRecord[ShapeType] with ObjectIdPk[ShapeType]{

  override def meta = ShapeType

  object nameType extends StringField(this, 100)
}

object ShapeType extends ShapeType with RogueMetaRecord[ShapeType]

// I put here shapeType : ShapeType but not run
trait Shape{
  val name: String
  val shapeType : ObjectId
}

case class Square(
  name: String,
  shapeType : ObjectId,
  side: Int
) extends Shape{
  def meta = Square
}

case class Triangle(
  name: String,
  shapeType : ObjectId,
  base: Int,
  height: Int
) extends Shape{
  def meta = Triangle
}

case class Circle(
  name: String,
  shapeType: ObjectId,
  radius: Int
) extends Shape{
  def meta = Circle
}

class ShapeCollection private() extends MongoRecord[ShapeCollection] with ObjectIdPk[ShapeCollection]{

  override def meta = ShapeCollection

  object listShapes extends MongoCaseClassListField[ShapeCollection, Shape](this){
    override def formats = Serialization.formats(ShortTypeHints(List(classOf[Square], classOf[Triangle], classOf[Circle])))
  }
}

object ShapeCollection extends ShapeCollection with RogueMetaRecord[ShapeCollection]

val shapeType1 = ShapeType.createRecord
    .nameType("Square")
  shapeType1.save(true)


val shapeType2 = ShapeType.createRecord
    .nameType("Triangle")
  shapeType2.save(true)


val shapeType3 = ShapeType.createRecord
    .nameType("Square")
  shapeType3.save(true)

val square = Square("square", shapeType1.id.get, 10)
val triangle = Triangle("triangle", shapeType2.id.get, 10, 5)
val circle = ("circle", shapeType3.id.get, 10)

val collect= ShapeCollection.createRecord
    .listShapes(List(square, triangle, circle))
    val collectSaved = collect.save
println(collectSaved)

// it print this

class code.model.ShapeCollection={ _id=54f9b0758ff616651d8e3555, listShapes=Lis
t(Square(square,54e7a672cbc215cfdd54765d,10), Triangle
(triangle,54e7a672cbc215cfdd54766d,10,5), Circle(circle,64e7a672cbc215cfdd54765d,10))}

In other snippet I call:
val collect = ShapeCollection.findAll.headOption.getOrElse(ShapeCollection.createRecord)
println(collect)
// it print this


class code.model.ShapeCollection={ _id=54f9b0758ff616651d8e3555, listShapes=Lis
t(
)}


The result on db:

db.shapeCollections.find()

{ "_id" : ObjectId("
54f8d2558ff6969fdcf80661"), "references" : [        {       "jsonClass" : "Square
",      "name" : "square",  "shapeType" : {      } , "side" : "10"} , {       "jsonClass" : "Triangle
",      "name" : "triangle",  "shapeType" : {      } , "base" : "10", "height" : "5"} ,{       "jsonClass" : "Circle
",      "name" : "circle",  "shapeType" : {      } , "radius" : "10"} ] }

Why return a empty List?
Why on data base not datas for shapeType show?

Thanks in advance

Tim Nelson

unread,
Mar 6, 2015, 9:26:24 AM3/6/15
to lif...@googlegroups.com
Hi Nataly,

The only way you're going to get this to work is to write your own asDBObject and fromDBObject functions on the Field. I'll try to write an example in the next few days.

Tim

Nataly Nanda Huanca Patzi

unread,
Mar 6, 2015, 9:32:58 AM3/6/15
to lif...@googlegroups.com
Ok thank you so much Tim, I will wait for your answer.

Tim Nelson

unread,
Mar 11, 2015, 11:34:42 AM3/11/15
to lif...@googlegroups.com
Hi Nataly,

I was able to get an example working using case classes, MongoCaseClassListField, and TypeHints. The example is here [1].

Since it uses case classes you're not able to save the individual shapes, just as part of the list. If this is something you need, we could probably do something similar with BsonRecordListField.

Tim

Nataly Nanda Huanca Patzi

unread,
Mar 11, 2015, 3:50:18 PM3/11/15
to lif...@googlegroups.com
Hi Tim,
Thanks for your aswer

I have this problem:

I published my project updated here:

https://github.com/natalynanda/inheritance/blob/master/src/main/scala/code/model/Shape.scala

If you can see, I added a shapeType in Shape trait, because I need an ObjectId type, all was compiled fine, but when I want get the saved listShapes it show me an empty list.

List(class code.model.ShapeCollection={_id=550098d68ff6bc03da076dc4, shapes=List()})

some times show me

{ "_id" : ObjectId("54f8d2558ff6969fdcf80661"), "shapes" : [        {       "jsonClass" : "Square

",      "name" : "square",  "shapeType" : {      } , "side" : "10"} , {       "jsonClass" : "Triangle
",      "name" : "triangle",  "shapeType" : {      } , "base" : "10", "height" : "5"} ,{       "jsonClass" : "Circle
",      "name" : "circle",  "shapeType" : {      } , "radius" : "10"} ] }

the field shapeType Empty,

In case clase is necesary to use primitive datas too?
Or This might work?

Tim Nelson

unread,
Mar 11, 2015, 6:41:39 PM3/11/15
to lif...@googlegroups.com
You just need to add the ObjectIdSerializer to your formats:

import net.liftweb.mongodb.ObjectIdSerializer

override implicit lazy val formats: Formats =
  DefaultFormats.withHints(
    ShortTypeHints(List(classOf[Circle], classOf[Square], classOf[Triangle]))
  ) + new ObjectIdSerializer


Nataly Nanda Huanca Patzi

unread,
Mar 13, 2015, 5:12:27 PM3/13/15
to lif...@googlegroups.com

Thanks so much, it working fine.

Reply all
Reply to author
Forward
0 new messages