Last active
January 12, 2018 14:45
-
-
Save bhameyie/8276017 to your computer and use it in GitHub Desktop.
Casbah tutorial (sort of)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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" | |
) | |
) | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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