Skip to content

Instantly share code, notes, and snippets.

@alaz
Created January 20, 2012 13:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alaz/1647326 to your computer and use it in GitHub Desktop.
Save alaz/1647326 to your computer and use it in GitHub Desktop.
Subset: "Blog post - comments" example
package com.osinka.subset.examples
/**
* Data model from this MongoDB doc page:
* http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator
*/
// Use :paste mode
import com.mongodb._
import com.osinka.subset._
import SmartValues._
case class Comment(by: String, votes: Int, text: String)
case class BlogPost(title: String, comments: List[Comment])
object Comment {
val by = "by".fieldOf[String]
val votes = "votes".fieldOf[Int]
val text = "text".fieldOf[String]
// these two are required so that reading/writing of List[Comment] becomes possible
implicit val reader = ValueReader[Comment]({
case by(by) ~ votes(votes) ~ text(text) => new Comment(by, votes, text)
})
implicit val writer = {
def f(comment: Comment): DBObject =
(by -> comment.by) ~ (votes -> comment.votes) ~ (text -> comment.text)
ValueWriter(f _)
}
}
object BlogPost {
val title = "title".fieldOf[String]
val comments = "comments".subset(Comment).of[List[Comment]]
def toDBO(blogPost: BlogPost): DBObject =
(title -> blogPost.title) ~ (comments -> blogPost.comments)
}
// :paste mode off
import collection.JavaConversions._
val mongo = new Mongo("localhost")
val db = mongo getDB "test"
val coll = db getCollection "test"
// Let's save a BlogPost object
val blogPost = BlogPost("title", Comment("joe", 0, "joe's comment"):: Nil)
// There is a Document helper, it requires implicit T => DBObject
implicit def blogPostToDBO(bp: BlogPost): DBObject = BlogPost toDBO bp
val oid = Document.newDoc(blogPost) {(dbo: DBObject) => coll insert dbo} .right get
// well, you could simply do `coll.insert(dbo)`, but you cannot get the new doc's OID then
// Let's push another comment
coll.update(Document.DocumentId === oid, BlogPost.comments push Comment("mary", 1, "mary's comment"))
// Let's increment a Joe's comment vote
coll.update(BlogPost.comments.where{_.by === "joe"}, BlogPost.comments.matched.modify {_.votes inc 2})
// Joe's vote must be 2
coll.find(BlogPost.comments.elemMatch {comment => comment.by === "joe" && comment.votes === 2}).iterator foreach {
case BlogPost.title(t) ~ BlogPost.comments(clist) =>
println( new BlogPost(t, clist) )
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment