Skip to content

Instantly share code, notes, and snippets.

@bhameyie
Last active January 12, 2018 14:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bhameyie/8276017 to your computer and use it in GitHub Desktop.
Save bhameyie/8276017 to your computer and use it in GitHub Desktop.
Casbah tutorial (sort of)
// Add salat and casbah to your build.scala or build.sbt files.
object ElBuild extends Build {
val Organization = "your own"
val Version = "0.0.1-SNAPSHOT"
val ScalaVersion = "2.10.3"
val ScalatraVersion = "2.2.1"
resolvers += "Maven Central Server" at "http://repo1.maven.org/maven2"
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
lazy val core = Project(
"core",
file("."),
settings = Defaults.defaultSettings ++ Seq(
organization := Organization,
name := "Your App",
version := Version,
scalaVersion := ScalaVersion,
parallelExecution in Test := false,
libraryDependencies ++= Seq(
"org.mongodb" %% "casbah" % "2.6.3",
"com.novus" %% "salat" % "1.9.4"
)
)
)
}
package tut
import org.bson.types.ObjectId
case class Instrument(name:String, proficiencyScore:Int)
case class Comment(commenter:ObjectId, comment:String, _id:ObjectId=new ObjectId())
case class Artist(name:String, band:String, fame:Int, instruments:List[Band]=List(), instrumentsCount=0, _id:ObjectId=null)
case class Song(title:String, comments:List[Comment]=List(), commentCount:Int=0,
artists:List[ObjectId]=List(), artistCount: Int=0, _id:ObjectId=null )
// for 'Artist' and 'Song', I default '_id' to null as it is meant to be set by casbah on insert and retrieval
// the reason why 'Comment' has an id defaulted to a new ObjectId is because it is a ValueObject, not an entity (See Domain-Driven-Design by Eric Evans)
// 'comments' and 'artists' are defaulted to a new list to ensure the field appears in the collection so as to avoid weird nullref exceptions
import com.mongodb.casbah.{MongoClient, MongoClientURI}
import com.typesafe.config.ConfigFactory
object MongoFactory {
private val config = ConfigFactory.load()
private val DATABASE = config.getString("mongo.db")
private val server = MongoClientURI(config.getString("mongo.uri"))
private val client = MongoClient(server)
val database = client(DATABASE)
}
package tut
import scala.Some
import com.mongodb.casbah.commons.conversions.scala._
import com.mongodb.casbah.WriteConcern
import com.mongodb.casbah.Imports._
import com.novus.salat._
import com.novus.salat.global._
import org.bson.types.ObjectId
import com.mongodb.CommandResult
class ArtistRepository {
val artistsCollection = MongoFactory.database("Artists")
def addNew(artist: Artist): Artist = {
val dBObject = grater[Artist].asDBObject(artist)
artistsCollection.save(dBObject, WriteConcern.Safe) //WriteConcern.Safe ensures things get written to immediately
grater[Artist].asObject(dBObject) // once save is called, dbObject gets populated with the '_id' field
}
//This shows how to perform a field value change
def changeName(id:ObjectId, newName:String)={
val query = MongoDBObject("_id" -> id)
val update = $set("name" -> newName)
val result = artistsCollection.findAndModify(query = query, update = update)
result match {
case Some(x) => //success case
case _ => //failure case
}
}
def getById(id: ObjectId): Option[Artist] = {
val query = MongoDBObject("_id" -> id) // queries are in terms of MongoDBObject, which works almost like a map
val obj = artistsCollection.findOne(query)
obj match {
case Some(x) => Some(grater[Artist].asObject(x))
case _ => None
}
}
def findNotPlayingWithInstrument(intrument:String)={
//say we wanted to find any artist who couldnt play a given instrument
// we could use $ne for exact matches
val query = "intruments.name".$ne(intrument)
findAll(query)
}
//let's say that for whatever reason we want to find all artists either belong to a band or who could play a given instrument
def findByBandAndInstrument(band:String, instrument:String)={
//we could use the $or operator
val query = $or ( MongoDBObject("band"-> band),
MongoDBObject("intruments.name"-> instrument))
findAll(query)
}
private def findAll(query:MongoDBObject)={
val results = artistsCollection.find(query)
val artists = for (item <- results) yield grater[Artist].asObject(item)
artists.toList
}
}
package tut
import scala.Some
import com.mongodb.casbah.commons.conversions.scala._
import com.mongodb.casbah.WriteConcern
import com.mongodb.casbah.Imports._
import com.novus.salat._
import com.novus.salat.global._
import org.bson.types.ObjectId
import com.mongodb.CommandResult
case class OperationResponse(hasSucceeded: Boolean, errorMessage: String = "")
class SongRepository {
val songsCollection = MongoFactory.database("Songs")
//This shows how to Add an item to collection
def addComment(id: ObjectId, comment: Comment): OperationResponse = {
val updateQuery = $addToSet("comments" -> grater[Comment].asDBObject(comment)) ++
$inc("commentCount" -> 1)
val query = MongoDBObject("_id" -> id)
modify(query, updateQuery)
}
//Say for some reason we didn't like chatty commenter
def addOnlyOneCommentPerUser(id:ObjectId, comment:Comment): OperationResponse={
//we can refine the criteria using $not and $elemMatch
val notSameCommenter = "comments" $not { _ $elemMatch MongoDBObject("commenter"->comment.commenter) }
val updateQuery = $addToSet("comments" -> grater[Comment].asDBObject(comment)) ++
$inc("commentCount" -> 1)
val query = MongoDBObject("_id" -> id) ++ notSameCommenter
modify(query, updateQuery)
}
//This shows how to Remove an item from a collection
def removeComment(id: ObjectId, commentId: ObjectId): OperationResponse = {
val updateQuery = $pull("comments" -> MongoDBObject("_id" -> commentId)) ++ $inc("commentCount" -> -1)
val query = MongoDBObject("_id" -> id)
modify(query, updateQuery)
}
private def modify(query: MongoDBObject, update: MongoDBObject): OperationResponse = {
val result = songsCollection.findAndModify(query = query, update = update)
result match {
case Some(x) => OperationResponse(true)
case _ => OperationResponse(false, s"Operation Failed")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment