Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

More documentation and formatting.

  • Loading branch information...
commit 102e8fea3679d447e2a7ab80a9bda1cb427d96a7 1 parent 54251cc
@foursquare-markcc foursquare-markcc authored
View
12 src/main/scala/com/foursquare/rogue/Indexes.scala
@@ -25,12 +25,14 @@ case class MongoIndex1[R <: MongoRecord[R],
(f1: F1, m1: M1) extends MongoIndex[R] {
def asListMap = ListMap((f1.name, m1.value))
}
+
case class MongoIndex2[R <: MongoRecord[R],
F1 <: Field[_, R], M1 <: IndexModifier,
F2 <: Field[_, R], M2 <: IndexModifier]
(f1: F1, m1: M1, f2: F2, m2: M2) extends MongoIndex[R] {
def asListMap = ListMap((f1.name, m1.value), (f2.name, m2.value))
}
+
case class MongoIndex3[R <: MongoRecord[R],
F1 <: Field[_, R], M1 <: IndexModifier,
F2 <: Field[_, R], M2 <: IndexModifier,
@@ -38,6 +40,7 @@ case class MongoIndex3[R <: MongoRecord[R],
(f1: F1, m1: M1, f2: F2, m2: M2, f3: F3, m3: M3) extends MongoIndex[R] {
def asListMap = ListMap((f1.name, m1.value), (f2.name, m2.value), (f3.name, m3.value))
}
+
case class MongoIndex4[R <: MongoRecord[R],
F1 <: Field[_, R], M1 <: IndexModifier,
F2 <: Field[_, R], M2 <: IndexModifier,
@@ -48,6 +51,7 @@ case class MongoIndex4[R <: MongoRecord[R],
def asListMap = ListMap((f1.name, m1.value), (f2.name, m2.value), (f3.name, m3.value),
(f4.name, m4.value))
}
+
case class MongoIndex5[R <: MongoRecord[R],
F1 <: Field[_, R], M1 <: IndexModifier,
F2 <: Field[_, R], M2 <: IndexModifier,
@@ -59,6 +63,7 @@ case class MongoIndex5[R <: MongoRecord[R],
def asListMap = ListMap((f1.name, m1.value), (f2.name, m2.value), (f3.name, m3.value),
(f4.name, m4.value), (f5.name, m5.value))
}
+
case class MongoIndex6[R <: MongoRecord[R],
F1 <: Field[_, R], M1 <: IndexModifier,
F2 <: Field[_, R], M2 <: IndexModifier,
@@ -100,7 +105,9 @@ case class IndexBuilder[M <: MongoRecord[M]](rec: M with MongoMetaRecord[M]) {
(f1: M => F1, m1: M1, f2: M => F2, m2: M2,
f3: M => F3, m3: M3, f4: M => F4, m4: M4,
f5: M => F5, m5: M5): MongoIndex5[M, F1, M1, F2, M2, F3, M3, F4, M4, F5, M5] =
- MongoIndex5[M, F1, M1, F2, M2, F3, M3, F4, M4, F5, M5](f1(rec), m1, f2(rec), m2, f3(rec), m3, f4(rec), m4, f5(rec), m5)
+ MongoIndex5[M, F1, M1, F2, M2, F3, M3, F4, M4, F5, M5](
+ f1(rec), m1, f2(rec), m2, f3(rec), m3, f4(rec), m4, f5(rec), m5)
+
def index[F1 <: Field[_, M], M1 <: IndexModifier,
F2 <: Field[_, M], M2 <: IndexModifier,
F3 <: Field[_, M], M3 <: IndexModifier,
@@ -110,5 +117,6 @@ case class IndexBuilder[M <: MongoRecord[M]](rec: M with MongoMetaRecord[M]) {
(f1: M => F1, m1: M1, f2: M => F2, m2: M2,
f3: M => F3, m3: M3, f4: M => F4, m4: M4,
f5: M => F5, m5: M5, f6: M => F6, m6: M6): MongoIndex6[M, F1, M1, F2, M2, F3, M3, F4, M4, F5, M5, F6, M6] =
- MongoIndex6[M, F1, M1, F2, M2, F3, M3, F4, M4, F5, M5, F6, M6](f1(rec), m1, f2(rec), m2, f3(rec), m3, f4(rec), m4, f5(rec), m5, f6(rec), m6)
+ MongoIndex6[M, F1, M1, F2, M2, F3, M3, F4, M4, F5, M5, F6, M6](
+ f1(rec), m1, f2(rec), m2, f3(rec), m3, f4(rec), m4, f5(rec), m5, f6(rec), m6)
}
View
37 src/main/scala/com/foursquare/rogue/MongoHelpers.scala
@@ -9,11 +9,15 @@ import scala.collection.immutable.ListMap
object MongoHelpers {
case class AndCondition(clauses: List[QueryClause[_]], orCondition: Option[OrCondition])
+
case class OrCondition(conditions: List[AndCondition])
sealed case class MongoOrder(terms: List[(String, Boolean)])
+
sealed case class MongoModify(clauses: List[ModifyClause[_]])
- sealed case class MongoSelect[R, M <: MongoRecord[M]](fields: List[SelectField[_, M]], transformer: List[_] => R)
+
+ sealed case class MongoSelect[R, M <: MongoRecord[M]](fields: List[SelectField[_, M]],
+ transformer: List[_] => R)
private type PlainBaseQuery[M <: MongoRecord[M], R] = BaseQuery[M, R, _, _, _, _, _]
@@ -22,7 +26,9 @@ object MongoHelpers {
buildCondition(cond, BasicDBObjectBuilder.start, signature)
}
- def buildCondition(cond: AndCondition, builder: BasicDBObjectBuilder, signature: Boolean): DBObject = {
+ def buildCondition(cond: AndCondition,
+ builder: BasicDBObjectBuilder,
+ signature: Boolean): DBObject = {
val (rawClauses, safeClauses) = cond.clauses.partition(_.isInstanceOf[RawQueryClause])
// Normal clauses
@@ -48,7 +54,8 @@ object MongoHelpers {
rawClauses.foreach(_.extend(builder, signature))
// Optional $or clause (only one per "and" chain)
- cond.orCondition.foreach(or => builder.add("$or", QueryHelpers.list(or.conditions.map(buildCondition(_, signature = false)))))
+ cond.orCondition.foreach(or =>
+ builder.add("$or", QueryHelpers.list(or.conditions.map(buildCondition(_, signature = false)))))
builder.get
}
@@ -124,7 +131,8 @@ object MongoHelpers {
def buildFindAndModifyString[R, M <: MongoRecord[M]](mod: BaseFindAndModifyQuery[M, R], returnNew: Boolean, upsert: Boolean, remove: Boolean): String = {
val query = mod.query
- val sb = new StringBuilder("db.%s.findAndModify({ query: %s".format(query.meta.collectionName, buildCondition(query.condition)))
+ val sb = new StringBuilder("db.%s.findAndModify({ query: %s".format(
+ query.meta.collectionName, buildCondition(query.condition)))
query.order.foreach(o => sb.append(", sort: " + buildOrder(o).toString))
if (remove) sb.append(", remove: true")
sb.append(", update: " + buildModify(mod.mod).toString)
@@ -149,13 +157,15 @@ object MongoHelpers {
import QueryHelpers._
import MongoHelpers.MongoBuilder._
- private[rogue] def runCommand[T](description: => String, query: PlainBaseQuery[_, _])(f: => T): T = {
+ private[rogue] def runCommand[T](description: => String,
+ query: PlainBaseQuery[_, _])(f: => T): T = {
val start = System.currentTimeMillis
try {
f
} catch {
case e: Exception =>
- throw new RogueException("Mongo query on %s [%s] failed after %d ms".format(query.meta.mongoIdentifier,
+ throw new RogueException("Mongo query on %s [%s] failed after %d ms".
+ format(query.meta.mongoIdentifier,
description, System.currentTimeMillis - start), e)
} finally {
logger.log(description, query.signature, System.currentTimeMillis - start)
@@ -209,7 +219,8 @@ object MongoHelpers {
val query = modClause.query
val cnd = buildCondition(query.condition)
val ord = query.order.map(buildOrder)
- val sel = query.select.map(buildSelect) getOrElse buildSelectFromNames(query.meta.metaFields.view.map(_.name))
+ val sel = query.select.map(buildSelect) getOrElse
+ buildSelectFromNames(query.meta.metaFields.view.map(_.name))
val m = buildModify(modClause.mod)
lazy val description = buildFindAndModifyString(modClause, returnNew, upsert, remove)
@@ -251,15 +262,18 @@ object MongoHelpers {
validator.validateQuery(queryClause)
val cnd = buildCondition(queryClause.condition)
val ord = queryClause.order.map(buildOrder)
- val sel = queryClause.select.map(buildSelect) getOrElse buildSelectFromNames(queryClause.meta.metaFields.view.map(_.name))
+ val sel = queryClause.select.map(buildSelect) getOrElse
+ buildSelectFromNames(queryClause.meta.metaFields.view.map(_.name))
val hnt = queryClause.hint.map(buildHint)
lazy val description = buildQueryString(operation, queryClause)
runCommand(description, queryClause){
- MongoDB.useCollection(queryClause.meta.mongoIdentifier, queryClause.meta.collectionName) { coll =>
+ MongoDB.useCollection(queryClause.meta.mongoIdentifier, queryClause.meta.collectionName) {
+ coll =>
try {
- val cursor = coll.find(cnd, sel).limit(queryClause.lim getOrElse 0).skip(queryClause.sk getOrElse 0)
+ val cursor = coll.find(cnd, sel).limit(queryClause.lim getOrElse 0)
+ .skip(queryClause.sk getOrElse 0)
ord.foreach(cursor sort _)
queryClause.maxScan.foreach(cursor addSpecial("$maxScan", _))
queryClause.comment.foreach(cursor addSpecial("$comment", _))
@@ -267,7 +281,8 @@ object MongoHelpers {
f(cursor)
} catch {
case e: Exception =>
- throw new RogueException("Mongo query on %s [%s] failed".format(coll.getDB().getMongo().toString(), description), e)
+ throw new RogueException("Mongo query on %s [%s] failed".format(
+ coll.getDB().getMongo().toString(), description), e)
}
}
}
View
54 src/main/scala/com/foursquare/rogue/QueryClause.scala
@@ -5,6 +5,10 @@ package com.foursquare.rogue
import com.mongodb.DBObject
import com.mongodb.BasicDBObjectBuilder
+/**
+ * An enumeration that defines the possible types of indexing that are supported by rogue
+ * query clauses.
+ */
object IndexBehavior extends Enumeration {
type IndexBehavior = Value
val Index = Value("Index")
@@ -13,60 +17,91 @@ object IndexBehavior extends Enumeration {
val DocumentScan = Value("Document scan")
}
+/*
+ * For each query clause, we define a class which computes the actual index behavior supported
+ * by the underlying object type, and the index behavior expected by the query.
+ */
+
class QueryClause[V](val fieldName: String, conditions: (CondOps.Value, V)*) {
def extend(q: BasicDBObjectBuilder, signature: Boolean): Unit = {
conditions foreach { case (op, v) => q.add(op.toString, if (signature) 0 else v) }
}
+
lazy val actualIndexBehavior = conditions.head._1 match {
case CondOps.All | CondOps.In => IndexBehavior.Index
- case CondOps.Gt | CondOps.GtEq | CondOps.Lt | CondOps.LtEq | CondOps.Ne | CondOps.Near => IndexBehavior.PartialIndexScan
+ case CondOps.Gt | CondOps.GtEq | CondOps.Lt | CondOps.LtEq | CondOps.Ne | CondOps.Near =>
+ IndexBehavior.PartialIndexScan
case CondOps.Mod | CondOps.Type => IndexBehavior.IndexScan
case CondOps.Exists | CondOps.Nin | CondOps.Size => IndexBehavior.DocumentScan
}
+
val expectedIndexBehavior = IndexBehavior.Index
- def withExpectedIndexBehavior(b: IndexBehavior.Value) = new QueryClause(fieldName, conditions: _*) { override val expectedIndexBehavior = b }
+
+ def withExpectedIndexBehavior(b: IndexBehavior.Value) = new QueryClause(fieldName, conditions: _*) {
+ override val expectedIndexBehavior = b
+ }
}
class RawQueryClause(f: BasicDBObjectBuilder => Unit) extends QueryClause("raw") {
override def extend(q: BasicDBObjectBuilder, signature: Boolean): Unit = {
f(q)
}
+
override lazy val actualIndexBehavior = IndexBehavior.DocumentScan
+
override val expectedIndexBehavior = IndexBehavior.DocumentScan
}
class EmptyQueryClause[V](fieldName: String) extends QueryClause[V](fieldName) {
override def extend(q: BasicDBObjectBuilder, signature: Boolean): Unit = {}
+
override lazy val actualIndexBehavior = IndexBehavior.Index
- override def withExpectedIndexBehavior(b: IndexBehavior.Value) = new EmptyQueryClause[V](fieldName) { override val expectedIndexBehavior = b }
+
+ override def withExpectedIndexBehavior(b: IndexBehavior.Value) =
+ new EmptyQueryClause[V](fieldName) {
+ override val expectedIndexBehavior = b
+ }
}
class EqClause[V](fieldName: String, value: V) extends QueryClause[V](fieldName) {
override def extend(q: BasicDBObjectBuilder, signature: Boolean): Unit = {
q.add(fieldName, if (signature) 0 else value)
}
+
override lazy val actualIndexBehavior = IndexBehavior.Index
- override def withExpectedIndexBehavior(b: IndexBehavior.Value) = new EqClause(fieldName, value) { override val expectedIndexBehavior = b }
+
+ override def withExpectedIndexBehavior(b: IndexBehavior.Value) =
+ new EqClause(fieldName, value) { override val expectedIndexBehavior = b }
}
-class WithinCircleClause[V](fieldName: String, lat: Double, lng: Double, radius: Double) extends QueryClause(fieldName) {
+class WithinCircleClause[V](fieldName: String, lat: Double, lng: Double, radius: Double)
+ extends QueryClause(fieldName) {
override def extend(q: BasicDBObjectBuilder, signature: Boolean): Unit = {
val value = if (signature) 0 else QueryHelpers.list(List(QueryHelpers.list(List(lat, lng)), radius))
q.push("$within").add("$center", value).pop
}
+
override lazy val actualIndexBehavior = IndexBehavior.PartialIndexScan
- override def withExpectedIndexBehavior(b: IndexBehavior.Value) = new WithinCircleClause[V](fieldName, lat, lng, radius) { override val expectedIndexBehavior = b }
+
+ override def withExpectedIndexBehavior(b: IndexBehavior.Value) =
+ new WithinCircleClause[V](fieldName, lat, lng, radius) {
+ override val expectedIndexBehavior = b
+ }
}
-class WithinBoxClause[V](fieldName: String, lat1: Double, lng1: Double, lat2: Double, lng2: Double) extends QueryClause(fieldName) {
+class WithinBoxClause[V](fieldName: String, lat1: Double, lng1: Double, lat2: Double, lng2: Double)
+ extends QueryClause(fieldName) {
override def extend(q: BasicDBObjectBuilder, signature: Boolean): Unit = {
val value = if (signature) 0 else {
QueryHelpers.list(List(QueryHelpers.list(lat1, lng1), QueryHelpers.list(lat2, lng2)))
}
q.push("$within").add("$box", value).pop
}
+
override lazy val actualIndexBehavior = IndexBehavior.PartialIndexScan
- override def withExpectedIndexBehavior(b: IndexBehavior.Value) = new WithinBoxClause[V](fieldName, lat1, lng1, lat2, lng2) { override val expectedIndexBehavior = b }
+
+ override def withExpectedIndexBehavior(b: IndexBehavior.Value) =
+ new WithinBoxClause[V](fieldName, lat1, lng1, lat2, lng2) { override val expectedIndexBehavior = b }
}
class ModifyClause[V](val operator: ModOps.Value, fields: (String, V)*) {
@@ -75,7 +110,8 @@ class ModifyClause[V](val operator: ModOps.Value, fields: (String, V)*) {
}
}
-class ModifyAddEachClause[V](fieldName: String, values: Traversable[V]) extends ModifyClause[V](ModOps.AddToSet) {
+class ModifyAddEachClause[V](fieldName: String, values: Traversable[V])
+ extends ModifyClause[V](ModOps.AddToSet) {
override def extend(q: BasicDBObjectBuilder): Unit = {
q.push(fieldName).add("$each", QueryHelpers.list(values)).pop
}
View
246 src/main/scala/com/foursquare/rogue/QueryField.scala
@@ -14,12 +14,16 @@ import net.liftweb.mongodb.record.field.{BsonRecordField, BsonRecordListField, M
import org.bson.types.ObjectId
import org.joda.time._
-object CondOps extends Enumeration(0, "$ne", "$lt", "$gt", "$lte", "$gte", "$in", "$nin", "$near", "$all", "$size", "$exists", "$type", "$mod") {
+object CondOps extends Enumeration(0, "$ne", "$lt", "$gt", "$lte", "$gte",
+ "$in", "$nin", "$near", "$all", "$size",
+ "$exists", "$type", "$mod") {
type Op = Value
val Ne, Lt, Gt, LtEq, GtEq, In, Nin, Near, All, Size, Exists, Type, Mod = Value
}
-object ModOps extends Enumeration(0, "$inc", "$set", "$unset", "$push", "$pushAll", "$addToSet", "$pop", "$pull", "$pullAll", "$bit", "$rename") {
+object ModOps extends Enumeration(0, "$inc", "$set", "$unset", "$push", "$pushAll",
+ "$addToSet", "$pop", "$pull", "$pullAll", "$bit",
+ "$rename") {
type Op = Value
val Inc, Set, Unset, Push, PushAll, AddToSet, Pop, Pull, PullAll, Bit, Rename = Value
}
@@ -45,9 +49,12 @@ object MongoType extends Enumeration {
val MinKey = Value(255)
}
-//////////////////////////////////////////////////////////////////////////////////
-/// Query fields
-//////////////////////////////////////////////////////////////////////////////////
+// ********************************************************************************
+// *** Query fields
+// ********************************************************************************
+//
+// The types of fields that can be queried, and the particular query operations that each supports
+// are defined below.
abstract class AbstractQueryField[V, DB, M <: MongoRecord[M]](val field: Field[V, M]) {
def valueToDB(v: V): DB
@@ -64,13 +71,18 @@ class QueryField[V, M <: MongoRecord[M]](field: Field[V, M])
override def valueToDB(v: V) = v
def exists(b: Boolean) = new QueryClause(field.name, CondOps.Exists -> b)
+
def hastype(t: MongoType.Value) = new QueryClause(field.name, CondOps.Type -> t.id)
}
class CalendarQueryField[M <: MongoRecord[M]](val field: Field[java.util.Calendar, M]) {
def before(d: DateTime) = new QueryClause(field.name, CondOps.Lt -> d.toDate)
+
def after(d: DateTime) = new QueryClause(field.name, CondOps.Gt -> d.toDate)
- def between(d1: DateTime, d2: DateTime) = new QueryClause(field.name, CondOps.Gt -> d1.toDate, CondOps.Lt -> d2.toDate)
+
+ def between(d1: DateTime, d2: DateTime) = new QueryClause(field.name,
+ CondOps.Gt -> d1.toDate,
+ CondOps.Lt -> d2.toDate)
}
class EnumerationQueryField[M <: MongoRecord[M], E <: Enumeration#Value](field: Field[E, M])
@@ -80,27 +92,53 @@ class EnumerationQueryField[M <: MongoRecord[M], E <: Enumeration#Value](field:
class GeoQueryField[M <: MongoRecord[M]](field: Field[LatLong, M])
extends AbstractQueryField[LatLong, java.util.List[Double], M](field) {
- override def valueToDB(ll: LatLong) = QueryHelpers.list(List(ll.lat, ll.long))
+ override def valueToDB(ll: LatLong) =
+ QueryHelpers.list(List(ll.lat, ll.long))
+
+ def eqs(lat: Double, lng: Double) =
+ new EqClause(field.name, QueryHelpers.list(List(lat, lng)))
+
+ def neqs(lat: Double, lng: Double) =
+ new QueryClause(field.name,
+ CondOps.Ne -> QueryHelpers.list(List(lat, lng)))
+
+ def near(lat: Double, lng: Double, radius: Degrees) =
+ new QueryClause(field.name,
+ CondOps.Near -> QueryHelpers.list(List(lat, lng, QueryHelpers.radius(radius))))
+
+ def withinCircle(lat: Double, lng: Double, radius: Degrees) =
+ new WithinCircleClause(field.name, lat, lng, QueryHelpers.radius(radius))
- def eqs(lat: Double, lng: Double) = new EqClause(field.name, QueryHelpers.list(List(lat, lng)))
- def neqs(lat: Double, lng: Double) = new QueryClause(field.name, CondOps.Ne -> QueryHelpers.list(List(lat, lng)))
- def near(lat: Double, lng: Double, radius: Degrees) = new QueryClause(field.name, CondOps.Near -> QueryHelpers.list(List(lat, lng, QueryHelpers.radius(radius))))
- def withinCircle(lat: Double, lng: Double, radius: Degrees) = new WithinCircleClause(field.name, lat, lng, QueryHelpers.radius(radius))
- def withinBox(lat1: Double, lng1: Double, lat2: Double, lng2: Double) = new WithinBoxClause(field.name, lat1, lng1, lat2, lng2)
+ def withinBox(lat1: Double, lng1: Double, lat2: Double, lng2: Double) =
+ new WithinBoxClause(field.name, lat1, lng1, lat2, lng2)
}
abstract class AbstractNumericQueryField[V, DB, M <: MongoRecord[M]](field: Field[V, M])
extends AbstractQueryField[V, DB, M](field) {
def lt(v: V) = new QueryClause(field.name, CondOps.Lt -> valueToDB(v))
+
def gt(v: V) = new QueryClause(field.name, CondOps.Gt -> valueToDB(v))
+
def lte(v: V) = new QueryClause(field.name, CondOps.LtEq -> valueToDB(v))
+
def gte(v: V) = new QueryClause(field.name, CondOps.GtEq -> valueToDB(v))
+
def <(v: V) = lt(v)
+
def <=(v: V) = lte(v)
+
def >(v: V) = gt(v)
+
def >=(v: V) = gte(v)
- def between(v1: V, v2: V) = new QueryClause(field.name, CondOps.GtEq -> valueToDB(v1), CondOps.LtEq -> valueToDB(v2))
- def mod(by: Int, eq: Int) = new QueryClause(field.name, CondOps.Mod -> QueryHelpers.list(List(by, eq)))
+
+ def between(v1: V, v2: V) =
+ new QueryClause(field.name,
+ CondOps.GtEq -> valueToDB(v1),
+ CondOps.LtEq -> valueToDB(v2))
+
+ def mod(by: Int, eq: Int) =
+ new QueryClause(field.name,
+ CondOps.Mod -> QueryHelpers.list(List(by, eq)))
}
class NumericQueryField[V, M <: MongoRecord[M]](field: Field[V, M])
@@ -110,34 +148,60 @@ class NumericQueryField[V, M <: MongoRecord[M]](field: Field[V, M])
class ObjectIdQueryField[M <: MongoRecord[M]](override val field: Field[ObjectId, M])
extends NumericQueryField(field) {
- def before(d: DateTime) = new QueryClause(field.name, CondOps.Lt -> new ObjectId(d.toDate, 0, 0))
- def after(d: DateTime) = new QueryClause(field.name, CondOps.Gt -> new ObjectId(d.toDate, 0, 0))
- def between(d1: DateTime, d2: DateTime) = new QueryClause(field.name, CondOps.Gt -> new ObjectId(d1.toDate, 0, 0), CondOps.Lt -> new ObjectId(d2.toDate, 0, 0))
+ def before(d: DateTime) =
+ new QueryClause(field.name,
+ CondOps.Lt -> new ObjectId(d.toDate, 0, 0))
+
+ def after(d: DateTime) =
+ new QueryClause(field.name,
+ CondOps.Gt -> new ObjectId(d.toDate, 0, 0))
+
+ def between(d1: DateTime, d2: DateTime) =
+ new QueryClause(field.name,
+ CondOps.Gt -> new ObjectId(d1.toDate, 0, 0),
+ CondOps.Lt -> new ObjectId(d2.toDate, 0, 0))
}
-class ForeignObjectIdQueryField[M <: MongoRecord[M], T <: MongoRecord[T] with MongoId[T]](override val field: Field[ObjectId, M] with HasMongoForeignObjectId[T])
+class ForeignObjectIdQueryField[M <: MongoRecord[M], T <: MongoRecord[T]
+ with MongoId[T]](override val field: Field[ObjectId, M]
+ with HasMongoForeignObjectId[T])
extends ObjectIdQueryField[M](field) {
- def eqs(obj: T) = new EqClause(field.name, obj.id)
- def neqs(obj: T) = new QueryClause(field.name, CondOps.Ne -> obj.id)
- def in(objs: Traversable[T]) = QueryHelpers.inListClause(field.name, objs.map(_.id))
- def nin(objs: Traversable[T]) = new QueryClause(field.name, CondOps.Nin -> QueryHelpers.list(objs.map(_.id)))
+
+ def eqs(obj: T) =
+ new EqClause(field.name, obj.id)
+
+ def neqs(obj: T) =
+ new QueryClause(field.name, CondOps.Ne -> obj.id)
+
+ def in(objs: Traversable[T]) =
+ QueryHelpers.inListClause(field.name, objs.map(_.id))
+
+ def nin(objs: Traversable[T]) =
+ new QueryClause(field.name,
+ CondOps.Nin -> QueryHelpers.list(objs.map(_.id)))
}
class StringQueryField[M <: MongoRecord[M]](val field: Field[String, M]) {
- def startsWith(s: String) = new EqClause(field.name, Pattern.compile("^" + Pattern.quote(s)))
- def matches(p: Pattern) = new EqClause(field.name, p) {
- override lazy val actualIndexBehavior = IndexBehavior.DocumentScan
- }
+ def startsWith(s: String) =
+ new EqClause(field.name, Pattern.compile("^" + Pattern.quote(s)))
+
+ def matches(p: Pattern) =
+ new EqClause(field.name, p) {
+ override lazy val actualIndexBehavior = IndexBehavior.DocumentScan
+ }
+
def regexWarningNotIndexed(p: Pattern) = new EqClause(field.name, p)
}
class CaseClassQueryField[V, M <: MongoRecord[M]](val field: MongoCaseClassField[M, V]) {
- def unsafeField[F](name: String): SelectableDummyField[F, M] = new SelectableDummyField[F, M](field.owner, field.name + "." + name)
+ def unsafeField[F](name: String): SelectableDummyField[F, M] =
+ new SelectableDummyField[F, M](field.owner, field.name + "." + name)
}
class BsonRecordQueryField[M <: MongoRecord[M], B <: BsonRecord[B]](field: Field[B, M] with MandatoryTypedField[B])
extends AbstractNumericQueryField[B, DBObject, M](field) {
override def valueToDB(b: B) = b.asDBObject
+
def subfield[V](subfield: B => Field[V, B]): SelectableDummyField[V, M] = {
val rec = field.defaultValue // a hack to get at the embedded record
new SelectableDummyField[V, M](field.owner, field.name + "." + subfield(rec).name)
@@ -150,9 +214,11 @@ class BsonRecordQueryField[M <: MongoRecord[M], B <: BsonRecord[B]](field: Field
// whereas for normal queries, the same query would look like:
// { "field.subfield" : { "$gt" : 3 }}
// So, normally, we need to just have one level of nesting, but here we want two.
-class BsonRecordQueryFieldInPullContext[M <: MongoRecord[M], B <: BsonRecord[B]](field: Field[B, M] with MandatoryTypedField[B])
+class BsonRecordQueryFieldInPullContext[M <: MongoRecord[M], B <: BsonRecord[B]]
+ (field: Field[B, M] with MandatoryTypedField[B])
extends AbstractNumericQueryField[B, DBObject, M](field) {
override def valueToDB(b: B) = b.asDBObject
+
def subfield[V](subfield: B => Field[V, B]): SelectableDummyField[V, M] = {
val rec = field.defaultValue // a hack to get at the embedded record
new SelectableDummyField[V, M](field.owner, subfield(rec).name)
@@ -163,13 +229,27 @@ abstract class AbstractListQueryField[V, DB, M <: MongoRecord[M]](val field: Fie
def valueToDB(v: V): DB
def valuesToDB(vs: Traversable[V]) = vs.map(valueToDB _)
- def all(vs: Traversable[V]) = QueryHelpers.allListClause(field.name, valuesToDB(vs))
- def in(vs: Traversable[V]) = QueryHelpers.inListClause(field.name, valuesToDB(vs))
- def nin(vs: Traversable[V]) = new QueryClause(field.name, CondOps.Nin -> QueryHelpers.list(valuesToDB(vs)))
- def size(s: Int) = new QueryClause(field.name, CondOps.Size -> s)
- def contains(v: V) = new EqClause(field.name, valueToDB(v))
- def notcontains(v: V) = new QueryClause(field.name, CondOps.Ne -> valueToDB(v))
- def at(i: Int): DummyField[V, M] = new DummyField[V, M](field.owner, field.name + "." + i.toString)
+ def all(vs: Traversable[V]) =
+ QueryHelpers.allListClause(field.name, valuesToDB(vs))
+
+ def in(vs: Traversable[V]) =
+ QueryHelpers.inListClause(field.name, valuesToDB(vs))
+
+ def nin(vs: Traversable[V]) =
+ new QueryClause(field.name, CondOps.Nin -> QueryHelpers.list(valuesToDB(vs)))
+
+ def size(s: Int) =
+ new QueryClause(field.name, CondOps.Size -> s)
+
+ def contains(v: V) =
+ new EqClause(field.name, valueToDB(v))
+
+ def notcontains(v: V) =
+ new QueryClause(field.name, CondOps.Ne -> valueToDB(v))
+
+ def at(i: Int): DummyField[V, M] =
+ new DummyField[V, M](field.owner, field.name + "." + i.toString)
+
def idx(i: Int): DummyField[V, M] = at(i)
}
@@ -181,7 +261,9 @@ class ListQueryField[V, M <: MongoRecord[M]](field: Field[List[V], M])
class CaseClassListQueryField[V, M <: MongoRecord[M]](field: MongoCaseClassListField[M, V])
extends AbstractListQueryField[V, DBObject, M](field) {
override def valueToDB(v: V) = QueryHelpers.asDBObject(v)
- def unsafeField[F](name: String): DummyField[F, M] = new DummyField[F, M](field.owner, field.name + "." + name)
+
+ def unsafeField[F](name: String): DummyField[F, M] =
+ new DummyField[F, M](field.owner, field.name + "." + name)
}
class BsonRecordListQueryField[M <: MongoRecord[M], B <: BsonRecord[B]](field: BsonRecordListField[M, B])
@@ -195,7 +277,8 @@ class BsonRecordListQueryField[M <: MongoRecord[M], B <: BsonRecord[B]](field: B
}
class MapQueryField[V, M <: MongoRecord[M]](val field: Field[Map[String, V], M]) {
- def at(key: String): SelectableDummyField[V, M] = new SelectableDummyField[V, M](field.owner, field.name + "." + key)
+ def at(key: String): SelectableDummyField[V, M] =
+ new SelectableDummyField[V, M](field.owner, field.name + "." + key)
}
class EnumerationListQueryField[V <: Enumeration#Value, M <: MongoRecord[M]](field: Field[List[V], M])
@@ -204,9 +287,10 @@ class EnumerationListQueryField[V <: Enumeration#Value, M <: MongoRecord[M]](fie
}
-//////////////////////////////////////////////////////////////////////////////////
-/// Modify fields
-//////////////////////////////////////////////////////////////////////////////////
+// ********************************************************************************
+// *** Modify fields
+// ********************************************************************************
+
abstract class AbstractModifyField[V, DB, M <: MongoRecord[M]](val field: Field[V, M]) {
def valueToDB(v: V): DB
@@ -223,6 +307,7 @@ class ModifyField[V, M <: MongoRecord[M]](field: Field[V, M])
class CalendarModifyField[M <: MongoRecord[M]](field: Field[Calendar, M])
extends AbstractModifyField[Calendar, java.util.Date, M](field) {
override def valueToDB(c: Calendar) = c.getTime
+
def setTo(d: DateTime) = new ModifyClause(ModOps.Set, field.name -> d.toDate)
}
@@ -233,13 +318,19 @@ class EnumerationModifyField[M <: MongoRecord[M], E <: Enumeration#Value](field:
class GeoModifyField[M <: MongoRecord[M]](field: Field[LatLong, M])
extends AbstractModifyField[LatLong, java.util.List[Double], M](field) {
- override def valueToDB(ll: LatLong) = QueryHelpers.list(List(ll.lat, ll.long))
- def setTo(lat: Double, long: Double) = new ModifyClause(ModOps.Set, field.name -> QueryHelpers.list(List(lat, long)))
+ override def valueToDB(ll: LatLong) =
+ QueryHelpers.list(List(ll.lat, ll.long))
+
+ def setTo(lat: Double, long: Double) =
+ new ModifyClause(ModOps.Set,
+ field.name -> QueryHelpers.list(List(lat, long)))
}
class NumericModifyField[V, M <: MongoRecord[M]](val field: Field[V, M]) {
def inc(v: V) = new ModifyClause(ModOps.Inc, field.name -> v)
+
def bitAnd(v: V) = new ModifyBitAndClause(field.name, v)
+
def bitOr(v: V) = new ModifyBitOrClause(field.name, v)
}
@@ -255,20 +346,47 @@ class MapModifyField[V, M <: MongoRecord[M]](field: Field[Map[String, V], M])
abstract class AbstractListModifyField[V, DB, M <: MongoRecord[M]](val field: Field[List[V], M]) {
def valueToDB(v: V): DB
+
def valuesToDB(vs: Traversable[V]) = vs.map(valueToDB _)
- def setTo(vs: Traversable[V]) = new ModifyClause(ModOps.Set, field.name -> QueryHelpers.list(valuesToDB(vs)))
- def push(v: V) = new ModifyClause(ModOps.Push, field.name -> valueToDB(v))
- def pushAll(vs: Traversable[V]) = new ModifyClause(ModOps.PushAll, field.name -> QueryHelpers.list(valuesToDB(vs)))
- def addToSet(v: V) = new ModifyClause(ModOps.AddToSet, field.name -> valueToDB(v))
- def addToSet(vs: Traversable[V]) = new ModifyAddEachClause(field.name, valuesToDB(vs))
- def popFirst = new ModifyClause(ModOps.Pop, field.name -> -1)
- def popLast = new ModifyClause(ModOps.Pop, field.name -> 1)
- def pull(v: V) = new ModifyClause(ModOps.Pull, field.name -> valueToDB(v))
- def pullAll(vs: Traversable[V]) = new ModifyClause(ModOps.PullAll, field.name -> QueryHelpers.list(valuesToDB(vs)))
+ def setTo(vs: Traversable[V]) =
+ new ModifyClause(ModOps.Set,
+ field.name -> QueryHelpers.list(valuesToDB(vs)))
+
+ def push(v: V) =
+ new ModifyClause(ModOps.Push,
+ field.name -> valueToDB(v))
+
+ def pushAll(vs: Traversable[V]) =
+ new ModifyClause(ModOps.PushAll,
+ field.name -> QueryHelpers.list(valuesToDB(vs)))
+
+ def addToSet(v: V) =
+ new ModifyClause(ModOps.AddToSet,
+ field.name -> valueToDB(v))
+
+ def addToSet(vs: Traversable[V]) =
+ new ModifyAddEachClause(field.name, valuesToDB(vs))
+
+ def popFirst =
+ new ModifyClause(ModOps.Pop, field.name -> -1)
+
+ def popLast =
+ new ModifyClause(ModOps.Pop, field.name -> 1)
+
+ def pull(v: V) =
+ new ModifyClause(ModOps.Pull,
+ field.name -> valueToDB(v))
+
+ def pullAll(vs: Traversable[V]) =
+ new ModifyClause(ModOps.PullAll,
+ field.name -> QueryHelpers.list(valuesToDB(vs)))
+
def $: Field[V, M] = new DummyField[V, M](field.owner, field.name + ".$")
+
def pullWhere(clauseFuncs: (Field[V, M] => QueryClause[_])*) =
- new ModifyPullWithPredicateClause(field.name, clauseFuncs.map(cf => cf(new DummyField[V, M](field.owner, field.name))): _*)
+ new ModifyPullWithPredicateClause(field.name,
+ clauseFuncs.map(cf => cf(new DummyField[V, M](field.owner, field.name))): _*)
}
class ListModifyField[V, M <: MongoRecord[M]](field: Field[List[V], M])
@@ -299,13 +417,17 @@ class BsonRecordListModifyField[M <: MongoRecord[M], B <: BsonRecord[B]](field:
def pullObjectWhere[V](clauseFuncs: BsonRecordQueryFieldInPullContext[M, B] => QueryClause[_]*) = {
val rec = field.setFromJValue(JArray(JInt(0) :: Nil)).open_!.head // a gross hack to get at the embedded record
- new ModifyPullObjWithPredicateClause(field.name, clauseFuncs.map(cf => cf(new BsonRecordQueryFieldInPullContext(new MandatoryDummyField[B, M](field.owner, field.name, rec)))): _*)
+ new ModifyPullObjWithPredicateClause(
+ field.name,
+ clauseFuncs.map(cf => cf(
+ new BsonRecordQueryFieldInPullContext(
+ new MandatoryDummyField[B, M](field.owner, field.name, rec)))): _*)
}
}
-//////////////////////////////////////////////////////////////////////////////////
-/// Select fields
-//////////////////////////////////////////////////////////////////////////////////
+// ********************************************************************************
+// *** Select fields
+// ********************************************************************************
abstract class SelectField[V, M <: MongoRecord[M]](val field: Field[_, M]) {
// Input will be a Box of the value, and output will either be a Box of the value or the value itself
@@ -323,9 +445,9 @@ class OptionalSelectField[V, M <: MongoRecord[M]](override val field: Field[V, M
}
-//////////////////////////////////////////////////////////////////////////////////
-/// Dummy field
-//////////////////////////////////////////////////////////////////////////////////
+// ********************************************************************************
+// *** Dummy field
+// ********************************************************************************
trait AbstractDummyField[V, M <: MongoRecord[M]] extends Field[V, M] {
override val asJValue = JInt(0)
@@ -346,10 +468,14 @@ trait AbstractDummyField[V, M <: MongoRecord[M]] extends Field[V, M] {
class DummyField[V, M <: MongoRecord[M]](override val owner: M, override val name: String)
extends AbstractDummyField[V, M]
+
class SelectableDummyField[V, M <: MongoRecord[M]](override val owner: M, override val name: String)
extends OptionalTypedField[V]
with AbstractDummyField[V, M]
-class MandatoryDummyField[V, M <: MongoRecord[M]](override val owner: M, override val name: String, override val defaultValue: V)
+
+class MandatoryDummyField[V, M <: MongoRecord[M]](override val owner: M,
+ override val name: String,
+ override val defaultValue: V)
extends MandatoryTypedField[V] with AbstractDummyField[V, M] {
override def set(v: MyType) = v
override def toBoxMyType(v: ValueType): Full[V] = Full(v)
View
195 src/main/scala/com/foursquare/rogue/Rogue.scala
@@ -7,22 +7,39 @@ import java.util.Calendar
import net.liftweb.common._
import net.liftweb.mongodb.record._
import net.liftweb.record._
-import net.liftweb.mongodb.record.field.{BsonRecordField, BsonRecordListField, MongoCaseClassField, MongoCaseClassListField}
+import net.liftweb.mongodb.record.field.{BsonRecordField, BsonRecordListField, MongoCaseClassField,
+ MongoCaseClassListField}
import org.bson.types.ObjectId
+/**
+ * A utility trait containing typing shorthands, and a collection of implicit conversions that make query
+ * syntax much simpler.
+ *
+ *@see AbstractQuery for an example of the use of implicit conversions.
+ */
trait Rogue {
- type Query[T <: MongoRecord[T]] = AbstractQuery[T, T, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause]
- type OrderedQuery[T <: MongoRecord[T]] = AbstractQuery[T, T, Ordered, Unselected, Unlimited, Unskipped, HasNoOrClause]
+ type Query[T <: MongoRecord[T]] =
+ AbstractQuery[T, T, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause]
+
+ type OrderedQuery[T <: MongoRecord[T]] =
+ AbstractQuery[T, T, Ordered, Unselected, Unlimited, Unskipped, HasNoOrClause]
+
type PaginatedQuery[T <: MongoRecord[T]] = BasePaginatedQuery[T, T]
- type EmptyQuery[T <: MongoRecord[T]] = BaseEmptyQuery[T, T, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause]
+
+ type EmptyQuery[T <: MongoRecord[T]] =
+ BaseEmptyQuery[T, T, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause]
type ModifyQuery[T <: MongoRecord[T]] = AbstractModifyQuery[T]
- def OrQuery[M <: MongoRecord[M]](subqueries: AbstractQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, _]*): AbstractQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasOrClause] = {
+ def OrQuery[M <: MongoRecord[M]]
+ (subqueries: AbstractQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, _]*)
+ : AbstractQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasOrClause] = {
subqueries.toList match {
case Nil => throw new RogueException("No subqueries supplied to OrQuery", null)
case q :: qs => {
val orCondition = QueryHelpers.orConditionFromQueries(q :: qs)
- BaseQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasOrClause](q.meta, None, None, None, None, None, AndCondition(Nil, Some(orCondition)), None, None)
+ BaseQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasOrClause](
+ q.meta, None, None, None, None, None,
+ AndCondition(Nil, Some(orCondition)), None, None)
}
}
}
@@ -31,73 +48,163 @@ trait Rogue {
object Desc extends IndexModifier(-1)
object TwoD extends IndexModifier("2d")
- implicit def metaRecordToQueryBuilder[M <: MongoRecord[M]](rec: M with MongoMetaRecord[M]): BaseQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause] =
- BaseQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause](rec, None, None, None, None, None, AndCondition(Nil, None), None, None)
+ /* Following are a collection of implicit conversions which take a meta-record and convert it to
+ * a QueryBuilder. This allows users to write queries as "QueryType where ...".
+ */
+ implicit def metaRecordToQueryBuilder[M <: MongoRecord[M]]
+ (rec: M with MongoMetaRecord[M]): BaseQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause] =
+ BaseQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause](
+ rec, None, None, None, None, None, AndCondition(Nil, None), None, None)
+
implicit def metaRecordToModifyQuery[M <: MongoRecord[M]](rec: M with MongoMetaRecord[M]): AbstractModifyQuery[M] =
- BaseModifyQuery(metaRecordToQueryBuilder(rec), MongoModify(Nil))
+ BaseModifyQuery(metaRecordToQueryBuilder(rec), MongoModify(Nil))
+
implicit def metaRecordToIndexBuilder[M <: MongoRecord[M]](rec: M with MongoMetaRecord[M]): IndexBuilder[M] =
- IndexBuilder(rec)
+ IndexBuilder(rec)
- implicit def queryBuilderToModifyQuery[M <: MongoRecord[M]](query: AbstractQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause]): AbstractModifyQuery[M] = {
+
+ /* A couple of implicit conversions that take a query builder, and convert it to a modify. This allows
+ * users to write "RecordType.where(...).modify(...)".
+ */
+ implicit def queryBuilderToModifyQuery[M <: MongoRecord[M]]
+ (query: AbstractQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause])
+ : AbstractModifyQuery[M] = {
query match {
case q: BaseEmptyQuery[_, _, _, _, _, _, _] => new EmptyModifyQuery[M]
- case q: BaseQuery[_, _, _, _, _, _, _] => BaseModifyQuery[M](q.asInstanceOf[BaseQuery[M, M, Unordered, Unselected, Unlimited, Unskipped, HasNoOrClause]], MongoModify(Nil))
+ case q: BaseQuery[_, _, _, _, _, _, _] =>
+ BaseModifyQuery[M](q.asInstanceOf[BaseQuery[M, M, Unordered, Unselected, Unlimited,
+ Unskipped, HasNoOrClause]],
+ MongoModify(Nil))
}
}
- implicit def queryBuilderToFindAndModifyQuery[M <: MongoRecord[M], R, Ord <: MaybeOrdered, Sel <: MaybeSelected](query: AbstractQuery[M, R, Ord, Sel, Unlimited, Unskipped, HasNoOrClause]): AbstractFindAndModifyQuery[M, R] = {
+
+ implicit def queryBuilderToFindAndModifyQuery[M <: MongoRecord[M], R, Ord <: MaybeOrdered, Sel <: MaybeSelected]
+ (query: AbstractQuery[M, R, Ord, Sel, Unlimited, Unskipped, HasNoOrClause])
+ : AbstractFindAndModifyQuery[M, R] = {
query match {
case q: BaseEmptyQuery[_, _, _, _, _, _, _] => new EmptyFindAndModifyQuery[M, R]
- case q: BaseQuery[_, _, _, _, _, _, _] => BaseFindAndModifyQuery[M, R](q.asInstanceOf[BaseQuery[M, R, Ord, Sel, Unlimited, Unskipped, HasNoOrClause]], MongoModify(Nil))
+ case q: BaseQuery[_, _, _, _, _, _, _] =>
+ BaseFindAndModifyQuery[M, R](q.asInstanceOf[BaseQuery[M, R, Ord, Sel, Unlimited,
+ Unskipped, HasNoOrClause]],
+ MongoModify(Nil))
}
}
// QueryField implicits
implicit def fieldToQueryField[M <: MongoRecord[M], F](f: Field[F, M]): QueryField[F, M] = new QueryField(f)
- implicit def bsonRecordFieldToBsonRecordQueryField[M <: MongoRecord[M], B <: BsonRecord[B]](f: BsonRecordField[M, B]): BsonRecordQueryField[M, B] =
+
+ implicit def bsonRecordFieldToBsonRecordQueryField[M <: MongoRecord[M], B <: BsonRecord[B]]
+ (f: BsonRecordField[M, B]): BsonRecordQueryField[M, B] =
new BsonRecordQueryField[M, B](f)
- implicit def bsonRecordListFieldToBsonRecordListQueryField[M <: MongoRecord[M], B <: BsonRecord[B]](f: BsonRecordListField[M, B]) =
+
+ implicit def bsonRecordListFieldToBsonRecordListQueryField[M <: MongoRecord[M], B <: BsonRecord[B]]
+ (f: BsonRecordListField[M, B]) =
new BsonRecordListQueryField[M, B](f)
- implicit def calendarFieldToCalendarQueryField[M <: MongoRecord[M], F](f: Field[java.util.Calendar, M]): CalendarQueryField[M] = new CalendarQueryField(f)
- implicit def ccFieldToQueryField[M <: MongoRecord[M], F](f: MongoCaseClassField[M, F]): CaseClassQueryField[F, M] = new CaseClassQueryField[F, M](f)
- implicit def ccListFieldToListQueryField[M <: MongoRecord[M], F](f: MongoCaseClassListField[M, F]): CaseClassListQueryField[F, M] =
+
+ implicit def calendarFieldToCalendarQueryField[M <: MongoRecord[M], F]
+ (f: Field[java.util.Calendar, M]): CalendarQueryField[M] =
+ new CalendarQueryField(f)
+
+ implicit def ccFieldToQueryField[M <: MongoRecord[M], F](f: MongoCaseClassField[M, F]): CaseClassQueryField[F, M] =
+ new CaseClassQueryField[F, M](f)
+
+ implicit def ccListFieldToListQueryField[M <: MongoRecord[M], F]
+ (f: MongoCaseClassListField[M, F]): CaseClassListQueryField[F, M] =
new CaseClassListQueryField[F, M](f)
- implicit def doubleFieldtoNumericQueryField[M <: MongoRecord[M], F](f: Field[Double, M]): NumericQueryField[Double, M] = new NumericQueryField(f)
- implicit def enumerationFieldToEnumerationQueryField[M <: MongoRecord[M], F <: Enumeration#Value](f: Field[F, M]): EnumerationQueryField[M, F] =
+
+ implicit def doubleFieldtoNumericQueryField[M <: MongoRecord[M], F]
+ (f: Field[Double, M]): NumericQueryField[Double, M] =
+ new NumericQueryField(f)
+
+ implicit def enumerationFieldToEnumerationQueryField[M <: MongoRecord[M], F <: Enumeration#Value]
+ (f: Field[F, M]): EnumerationQueryField[M, F] =
new EnumerationQueryField(f)
- implicit def enumerationListFieldToEnumerationListQueryField[M <: MongoRecord[M], F <: Enumeration#Value](f: Field[List[F], M]): EnumerationListQueryField[F, M] =
+
+ implicit def enumerationListFieldToEnumerationListQueryField[M <: MongoRecord[M], F <: Enumeration#Value]
+ (f: Field[List[F], M]): EnumerationListQueryField[F, M] =
new EnumerationListQueryField[F, M](f)
- implicit def foreignObjectIdFieldToForeignObjectIdQueryField[M <: MongoRecord[M], T <: MongoRecord[T] with MongoId[T]](f: Field[ObjectId, M] with HasMongoForeignObjectId[T]): ForeignObjectIdQueryField[M, T] = new ForeignObjectIdQueryField(f)
- implicit def intFieldtoNumericQueryField[M <: MongoRecord[M], F](f: Field[Int, M]): NumericQueryField[Int, M] = new NumericQueryField(f)
- implicit def latLongFieldToGeoQueryField[M <: MongoRecord[M]](f: Field[LatLong, M]): GeoQueryField[M] = new GeoQueryField(f)
- implicit def listFieldToListQueryField[M <: MongoRecord[M], F](f: Field[List[F], M]): ListQueryField[F, M] = new ListQueryField[F, M](f)
- implicit def longFieldtoNumericQueryField[M <: MongoRecord[M], F](f: Field[Long, M]): NumericQueryField[Long, M] = new NumericQueryField(f)
- implicit def objectIdFieldToObjectIdQueryField[M <: MongoRecord[M], F](f: Field[ObjectId, M]): ObjectIdQueryField[M] = new ObjectIdQueryField(f)
- implicit def mapFieldToMapQueryField[M <: MongoRecord[M], F](f: Field[Map[String, F], M]): MapQueryField[F, M] = new MapQueryField[F, M](f)
- implicit def stringFieldToStringQueryField[M <: MongoRecord[M]](f: Field[String, M]): StringQueryField[M] = new StringQueryField(f)
+
+ implicit def foreignObjectIdFieldToForeignObjectIdQueryField[M <: MongoRecord[M],
+ T <: MongoRecord[T] with MongoId[T]]
+ (f: Field[ObjectId, M] with HasMongoForeignObjectId[T]): ForeignObjectIdQueryField[M, T] =
+ new ForeignObjectIdQueryField(f)
+
+ implicit def intFieldtoNumericQueryField[M <: MongoRecord[M], F](f: Field[Int, M]): NumericQueryField[Int, M] =
+ new NumericQueryField(f)
+
+ implicit def latLongFieldToGeoQueryField[M <: MongoRecord[M]](f: Field[LatLong, M]): GeoQueryField[M] =
+ new GeoQueryField(f)
+
+ implicit def listFieldToListQueryField[M <: MongoRecord[M], F](f: Field[List[F], M]): ListQueryField[F, M] =
+ new ListQueryField[F, M](f)
+
+ implicit def longFieldtoNumericQueryField[M <: MongoRecord[M], F](f: Field[Long, M]): NumericQueryField[Long, M] =
+ new NumericQueryField(f)
+
+ implicit def objectIdFieldToObjectIdQueryField[M <: MongoRecord[M], F](f: Field[ObjectId, M])
+ : ObjectIdQueryField[M] =
+ new ObjectIdQueryField(f)
+
+ implicit def mapFieldToMapQueryField[M <: MongoRecord[M], F](f: Field[Map[String, F], M]): MapQueryField[F, M] =
+ new MapQueryField[F, M](f)
+
+ implicit def stringFieldToStringQueryField[M <: MongoRecord[M]](f: Field[String, M]): StringQueryField[M] =
+ new StringQueryField(f)
// ModifyField implicits
implicit def fieldToModifyField[M <: MongoRecord[M], F](f: Field[F, M]): ModifyField[F, M] = new ModifyField(f)
- implicit def bsonRecordFieldToBsonRecordModifyField[M <: MongoRecord[M], B <: BsonRecord[B]](f: BsonRecordField[M, B]) =
+
+ implicit def bsonRecordFieldToBsonRecordModifyField[M <: MongoRecord[M], B <: BsonRecord[B]]
+ (f: BsonRecordField[M, B]) =
new BsonRecordModifyField[M, B](f)
- implicit def bsonRecordListFieldToBsonRecordListModifyField[M <: MongoRecord[M], B <: BsonRecord[B]](f: BsonRecordListField[M, B])(implicit mf: Manifest[B]): BsonRecordListModifyField[M, B] =
+
+ implicit def bsonRecordListFieldToBsonRecordListModifyField[M <: MongoRecord[M], B <: BsonRecord[B]]
+ (f: BsonRecordListField[M, B])(implicit mf: Manifest[B]): BsonRecordListModifyField[M, B] =
new BsonRecordListModifyField[M, B](f)(mf)
- implicit def calendarFieldToCalendarModifyField[M <: MongoRecord[M]](f: Field[Calendar, M]): CalendarModifyField[M] = new CalendarModifyField(f)
- implicit def ccListFieldToListModifyField[M <: MongoRecord[M], V](f: MongoCaseClassListField[M, V]): CaseClassListModifyField[V, M] =
+
+ implicit def calendarFieldToCalendarModifyField[M <: MongoRecord[M]](f: Field[Calendar, M]): CalendarModifyField[M] =
+ new CalendarModifyField(f)
+
+ implicit def ccListFieldToListModifyField[M <: MongoRecord[M], V]
+ (f: MongoCaseClassListField[M, V]): CaseClassListModifyField[V, M] =
new CaseClassListModifyField[V, M](f)
- implicit def doubleFieldToNumericModifyField[M <: MongoRecord[M]](f: Field[Double, M]): NumericModifyField[Double, M] = new NumericModifyField(f)
- implicit def enumerationFieldToEnumerationModifyField[M <: MongoRecord[M], F <: Enumeration#Value](f: Field[F, M]): EnumerationModifyField[M, F] =
+
+ implicit def doubleFieldToNumericModifyField[M <: MongoRecord[M]]
+ (f: Field[Double, M]): NumericModifyField[Double, M] =
+ new NumericModifyField(f)
+
+ implicit def enumerationFieldToEnumerationModifyField[M <: MongoRecord[M], F <: Enumeration#Value]
+ (f: Field[F, M]): EnumerationModifyField[M, F] =
new EnumerationModifyField(f)
- implicit def enumerationListFieldToEnumerationListModifyField[M <: MongoRecord[M], F <: Enumeration#Value](f: Field[List[F], M]): EnumerationListModifyField[F, M] =
+
+ implicit def enumerationListFieldToEnumerationListModifyField[M <: MongoRecord[M], F <: Enumeration#Value]
+ (f: Field[List[F], M]): EnumerationListModifyField[F, M] =
new EnumerationListModifyField[F, M](f)
- implicit def intFieldToIntModifyField[M <: MongoRecord[M]](f: Field[Int, M]): NumericModifyField[Int, M] = new NumericModifyField(f)
- implicit def latLongFieldToGeoQueryModifyField[M <: MongoRecord[M]](f: Field[LatLong, M]): GeoModifyField[M] = new GeoModifyField(f)
- implicit def listFieldToListModifyField[M <: MongoRecord[M], F](f: Field[List[F], M]): ListModifyField[F, M] = new ListModifyField[F, M](f)
- implicit def longFieldToNumericModifyField[M <: MongoRecord[M]](f: Field[Long, M]): NumericModifyField[Long, M] = new NumericModifyField(f)
- implicit def mapFieldToMapModifyField[M <: MongoRecord[M], F](f: Field[Map[String, F], M]): MapModifyField[F, M] = new MapModifyField[F, M](f)
+
+ implicit def intFieldToIntModifyField[M <: MongoRecord[M]]
+ (f: Field[Int, M]): NumericModifyField[Int, M] =
+ new NumericModifyField(f)
+
+ implicit def latLongFieldToGeoQueryModifyField[M <: MongoRecord[M]](f: Field[LatLong, M]): GeoModifyField[M] =
+ new GeoModifyField(f)
+
+ implicit def listFieldToListModifyField[M <: MongoRecord[M], F](f: Field[List[F], M]): ListModifyField[F, M] =
+ new ListModifyField[F, M](f)
+
+ implicit def longFieldToNumericModifyField[M <: MongoRecord[M]](f: Field[Long, M]): NumericModifyField[Long, M] =
+ new NumericModifyField(f)
+
+ implicit def mapFieldToMapModifyField[M <: MongoRecord[M], F](f: Field[Map[String, F], M]): MapModifyField[F, M] =
+ new MapModifyField[F, M](f)
// SelectField implicits
- implicit def mandatoryFieldToSelectField[M <: MongoRecord[M], V](f: Field[V, M] with MandatoryTypedField[V]): SelectField[V, M] = new MandatorySelectField(f)
- implicit def optionalFieldToSelectField[M <: MongoRecord[M], V](f: Field[V, M] with OptionalTypedField[V]): SelectField[Box[V], M] = new OptionalSelectField(f)
+ implicit def mandatoryFieldToSelectField[M <: MongoRecord[M], V]
+ (f: Field[V, M] with MandatoryTypedField[V]): SelectField[V, M] =
+ new MandatorySelectField(f)
+
+ implicit def optionalFieldToSelectField[M <: MongoRecord[M], V]
+ (f: Field[V, M] with OptionalTypedField[V]): SelectField[Box[V], M] =
+ new OptionalSelectField(f)
}
object Rogue extends Rogue
Please sign in to comment.
Something went wrong with that request. Please try again.