Last active
December 10, 2015 03:28
-
-
Save ktoso/4374274 to your computer and use it in GitHub Desktop.
A basic "rogue" (from foursquare) MongoDB querying library. It'll be used to display how rogue does things, but keeping all stuff nice and simple and in just 80 lines of code. I'll be presenting about this and rogue on the upcoming ScalaCamp Kraków.package pl.project13.scala.workshop.rogue.ourown
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 pl.project13.scala.workshop.rogue.model | |
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord} | |
import net.liftweb.mongodb.record.field.{MongoListField, IntPk} | |
import net.liftweb.record.field._ | |
import pl.project13.scala.workshop.mongo.MongoConfig.MainMongoIdentifier | |
class Person extends MongoRecord[Person] with IntPk[Person] { | |
override val meta = Person | |
object name extends StringField(this, 16) | |
object middleName extends OptionalStringField(this, 16) { | |
override val name = "middle_name" | |
} | |
object lastName extends StringField(this, 64) | |
object age extends IntField(this) | |
object hobbies extends MongoListField[Person, String](this) | |
} | |
object Person extends Person with MongoMetaRecord[Person] { | |
override def mongoIdentifier = MainMongoIdentifier | |
override def collectionName = "persons" | |
def ensureIndexes() { | |
// todo ensure indexes | |
} | |
// todo add finders | |
def ??? = throw new RuntimeException("Not Implemented Yet!") // in case you're not 2.10 ;-) | |
def findByName(name: String) = { | |
import pl.project13.scala.workshop.rogue.ourown.OwnRogueDSL._ | |
meta where(_.name eqs name) findAll() | |
} | |
def findByAge(min: Int, max: Option[Int] = None) = ??? | |
} |
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 net.liftweb.mongodb.record._ | |
import field.MongoListField | |
import net.liftweb.record.field._ | |
import net.liftweb.record.{Field, Record, BaseField} | |
import net.liftweb.json.JsonAST.JValue | |
import net.liftweb.mongodb.MongoDB | |
import com.mongodb.BasicDBObject | |
trait WhereDSLImplicits { | |
// entry points ... | |
implicit def addRogueDSL[M <: MongoRecord[M]](meta: MongoMetaRecord[M]) = | |
new OwnRogueMonad(meta, meta.createRecord) | |
// fields ... | |
implicit def addStringFieldClauses[M <: MongoRecord[M]](field: StringField[M]) = | |
new StringFieldClauses(field) | |
implicit def addStringListFieldClauses[M <: MongoRecord[M]](field: MongoListField[M, String]) = // hardcoded List[String] | |
new SimpleListFieldClauses(field) | |
} | |
trait OwnRogueDSL | |
extends WhereDSLImplicits | |
trait QueryField { | |
def field: BaseField | |
} | |
trait DefaultQueryField extends QueryField { | |
def eqs(value: String) = WhereQuery(field.name, value) | |
def neqs(value: String) = WhereQuery(field.name, "neqs", value) | |
} | |
trait NumericQueryField extends QueryField { | |
def gt(value: String) = WhereQuery(field.name, "gt", value) | |
def gte(value: String) = WhereQuery(field.name, "gte", value) | |
def lt(value: String) = WhereQuery(field.name, "lt", value) | |
def lte(value: String) = WhereQuery(field.name, "lte", value) | |
} | |
case class StringFieldClauses(override val field: BaseField) extends DefaultQueryField | |
case class SimpleListFieldClauses(override val field: BaseField) extends QueryField { | |
def contains(s: String) = WhereQuery(field.name, s) | |
def size(size: Int) = WhereQuery(field.name, "$size", size.toString) | |
def doesntContain(s: String) = WhereQuery(field.name, "$ne", s) | |
} | |
class OwnRogueMonad[Owner <: MongoRecord[Owner]]( | |
meta: MongoMetaRecord[Owner], | |
record: Owner, | |
val whereParts: List[WhereQuery] = Nil) { | |
def where(queryOn: Owner => WhereQuery) = | |
new OwnRogueMonad( | |
meta, | |
meta.createRecord, | |
whereParts = queryOn(record) :: whereParts | |
) | |
def findAll(): List[Owner] = { | |
MongoDB.useCollection(meta.mongoIdentifier, meta.collectionName) { db => | |
val queryObject = new BasicDBObject() | |
whereParts | |
val cursor = db.find(queryObject) | |
import collection.JavaConversions._ | |
cursor.iterator.map(meta.fromDBObject).toList | |
} | |
} | |
@inline def get(): Option[Owner] = findOne() | |
def findOne(): Option[Owner] = { | |
MongoDB.useCollection(meta.mongoIdentifier, meta.collectionName) { db => | |
val queryObject = new BasicDBObject() | |
whereParts | |
val cursor = db.find(queryObject) | |
import collection.JavaConversions._ | |
cursor.headOption.map(meta.fromDBObject) | |
} | |
} | |
} | |
object OwnRogueDSL extends OwnRogueDSL | |
// clauses ------------------------------------------------------------------------------------------------------------- | |
sealed abstract class Query | |
case class WhereQuery(json: JValue) extends Query | |
object WhereQuery { | |
import net.liftweb.json.JsonDSL._ | |
def apply(field: String, value: String) = | |
new WhereQuery(field -> value) | |
def apply(field: String, value: Number) = | |
new WhereQuery(field -> value) | |
def apply(field: String, operator: String, value: String) = | |
new WhereQuery(field -> (operator -> value)) | |
def apply(field: String, operator: String, value: Number) = | |
new WhereQuery(field -> (operator -> value)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment