Created
November 6, 2011 21:46
-
-
Save bwmcadams/1343568 to your computer and use it in GitHub Desktop.
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
/* I'm trying to refactor $and and $or (which are essentially the same code returning a different outer query). | |
The problem is that currently only "String, Any" pairs work, and I need to be able to combine both those *AND* "Query Expression Objects". | |
Here's the $or spec right now | |
*/ | |
"Casbah's DSL $or Operator" should { | |
"Accept multiple values" in { | |
val or = $or("foo" -> "bar", "x" -> "y") | |
or must haveListEntry("$or", Seq(MongoDBObject("foo" -> "bar"), MongoDBObject("x" -> "y"))) | |
} | |
"Work with nested operators" in { | |
val or = $or( "foo" $lt 5 $gt 1, "x" $gte 10 $lte 152 ) | |
or must haveSuperclass[BasicBSONList] | |
or must beEqualTo(MongoDBObject("$or" -> MongoDBList(MongoDBObject("foo" -> "bar", "x" -> "y")))) | |
} | |
} | |
/** | |
the second block doesn't compile or work and I need to figure out an idiom that works. | |
I've fiddled with a few things but Type Classes don't work due to needing a wildcard / <: on the second arg to the tuple pairs. | |
*/ |
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
/** | |
* Trait to provide the $or method as a bareword operator. | |
* | |
* $or ("Foo" -> "bar") | |
* | |
* Targets an RValue of (String, Any)* to be converted to a DBObject | |
* | |
* TODO - Test that rvalue ends up being an array e.g.: | |
* | |
* scala> $or ("foo" -> "bar", "X" -> 5) | |
* res1: com.mongodb.casbah.commons.Imports.DBObject = { "$or" : [ { "foo" : "bar" , "X" : 5}]} | |
* | |
* | |
* @author Brendan W. McAdams <brendan@10gen.com> | |
* @since 2.0 | |
* @see http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24or | |
*/ | |
trait OrOp extends BarewordQueryOperator { | |
def $or(fields: (String, Any)*) = { | |
val bldr = MongoDBList.newBuilder | |
for ((k, v) <- fields) bldr += MongoDBObject(k -> v) | |
MongoDBObject("$or" -> bldr.result) | |
} | |
} |
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
/** | |
* Trait to provide the $or method as a bareword operator. | |
* | |
* $or ("Foo" -> "bar") | |
* | |
* Targets an RValue of (String, Any)* to be converted to a DBObject | |
* | |
* TODO - Test that rvalue ends up being an array e.g.: | |
* | |
* scala> $or ("foo" -> "bar", "X" -> 5) | |
* res1: com.mongodb.casbah.commons.Imports.DBObject = { "$or" : [ { "foo" : "bar" , "X" : 5}]} | |
* | |
* | |
* @author Brendan W. McAdams <brendan@10gen.com> | |
* @since 2.0 | |
* @see http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24or | |
*/ | |
trait OrOp extends BarewordQueryOperator { | |
def $or(fields: (String, Any)*) = { | |
val bldr = MongoDBList.newBuilder | |
for ((k, v) <- fields) bldr += MongoDBObject(k -> v) | |
MongoDBObject("$or" -> bldr.result) | |
} | |
} |
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
trait OrOp extends BarewordQueryOperator { | |
def $or(fields: (String, Any)*) = { | |
val bldr = MongoDBList.newBuilder | |
for ((k, v) <- fields) bldr += MongoDBObject(k -> v) | |
MongoDBObject("$or" -> bldr.result) | |
} | |
def $or[A : ValidBarewordExpressionArgType](fields: A*) = | |
MongoDBObject("$or" -> implicitly[ValidBarewordExpressionArgType[A]].listify(fields)) | |
} | |
trait ValidTypes { | |
trait KVPair extends ValidBarewordExpressionArgType[(String, Any)] { | |
def listify(args: Seq[(String, Any)]): Seq[DBObject] = { | |
val bldr = MongoDBList.newBuilder | |
args.foreach(kv => bldr += MongoDBObject(kv)) | |
bldr.result.asInstanceOf[Seq[DBObject]] | |
} | |
} | |
// Valid Bareword Query Expression entries | |
trait CoreOperatorResultObj extends ValidBarewordExpressionArgType[DBObject with QueryExpressionObject] { | |
def listify(args: Seq[DBObject with QueryExpressionObject]): Seq[DBObject] = { | |
val bldr = MongoDBList.newBuilder | |
args.foreach(bldr.+=) | |
bldr.result.asInstanceOf[Seq[DBObject]] | |
} | |
} | |
} | |
trait ValidBarewordExpressionArgTypeHolder { | |
import com.mongodb.casbah.query.ValidTypes.{CoreOperatorResultObj, KVPair} | |
implicit object KVPairOk extends CoreOperatorResultObj | |
implicit object CoreOperatorResultObjOk extends CoreOperatorResultObj | |
} | |
/** | |
Compile Error: | |
[error] /Users/bwmcadams/code/mongodb/casbah/casbah-query/src/test/scala/BarewordOperatorsSpec.scala:79: could not find implicit value for evidence parameter of type com.mongodb.casbah.query.ValidBarewordExpressionArgType[(java.lang.String, java.lang.String)] | |
[error] val or = $or("foo" -> "bar", "x" -> "y") | |
[error] ^ | |
*/ |
I tried the type class approach, but a TypeClass of (String, Any) won't allow say "a" -> "b" as it says it is looking for a typeclass of (String, String)
Try defining the typeclass in terms of (String, A)
for some type parameter A
.
@djspiewak - That won't work, as you can't give the implicit instance a wildcard arg... unless there's some syntax I'm missing?
See my updated "3rd" file.
Forked and updated with working syntax. You can parameterize an implicit value by using def
rather than val
or object
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can solve the problem listed in the comments of the first file by using a typeclass to represent the things that are composable via
$or
and friends. Provide one instance of the typeclass for(String, Any)
, another instance for "query expression objects".Update: Just read your trailing comment. Thinking...