Reputation: 1336
I'm learning Scala and trying Mongo too. I'm creating a function that receives a Map[String, Any]
as a parameter and I would like to return the proper MongoDBObject
for it:
def parse(query: Map[String, Any]): MongoDBObject = {
val result = query("operation") match {
case "all" => query("field").toString $all query("value").asInstanceOf[List[String]]
case "in" => query("field").toString $in query("value").asInstanceOf[List[String]]
case "regex" => query("field").toString $regex query("value")
case "eq" => query("field").toString $eq query("value")
case "gt" => query("field").toString $gt query("value")
case "gte" => query("field").toString $gte query("value")
case "lt" => query("field").toString $lt query("value")
case "lte" => query("field").toString $lte query("value")
case "exists" => query("field").toString $exists query("value").asInstanceOf[Boolean]
case "size" => query("field").toString $size query("value").asInstanceOf[Int]
case "where" => $where(query("value").toString)
case _ => throw new NotImplementedError("Unknown operation")
}
}
I have some issues.
$regex
is not a member of String
. I don't know why. Any
is not a valid query parameter. I suppose I should cast to int, string, date or any other valid Mongo type. Is there any way to fix this without reflection to solve wich type the value is?$mod
operation I should give two numeric values as parameteres. Should I use a List
as value for the map and get first and second items?Upvotes: 0
Views: 735
Reputation: 1010
It complains about $regex
because it isn't finding a regex-able object on the right hand side to apply the conversion used to parse the $regex
method--this is a problem you will run into with all of the following calls as well.
For the issue with Any
(and also $mod
), may I suggest a different approach? You have no type information with Any
, so you can't really get around runtime casting (and I'm not sure how reflection would help you either.) You're not getting any of the benefits of a static type system that way. Here's a sketch of one way you could implement a method like this using a type hierarchy to enforce type safety:
sealed trait Query
case class All(field: String, value: List[String]) extends Query
...
case class GreaterThan(field: String, value: Int) extends Query
...
case class Mod(field: String, divisor: Int, remainder: Int) extends Query
def parse(q: Query): MongoDBObject = {
q match {
case All(f, v) => f $all v
...
case GreaterThan(f, v) => f $gt v
...
case Mod(f, d, r) => f $mod (d, r)
}
}
Alternately, you could define an abstract execute method on Query
and override it in each extending class instead of doing the match
statement in parse
. From there, you could abstract further using type parameters or generic types to allow, for example, GreaterThan
to take any Numeric
type.
Upvotes: 1