Scala Casbah DSL запросы
Я изучаю Scala и пробую Mongo тоже. Я создаю функцию, которая получает Map[String, Any]
в качестве параметра, и я хотел бы вернуть правильное MongoDBObject
для этого:
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")
}
}
У меня есть некоторые проблемы.
- компилятор говорит
$regex
не является членомString
, Я не знаю почему. - компилятор говорит, что
Any
не является допустимым параметром запроса. Я полагаю, я должен привести к int, string, date или любому другому допустимому типу Mongo. Есть ли способ исправить это, не задумываясь, чтобы решить, какой тип значения? - для
$mod
операции я должен дать два числовых значения в качестве параметров. Должен ли я использоватьList
в качестве значения для карты и получения первого и второго элементов?
1 ответ
Жалуется на $regex
потому что он не находит regex-способный объект с правой стороны, чтобы применить преобразование, используемое для анализа $regex
Метод - это проблема, с которой вы также столкнетесь при следующих вызовах.
Для вопроса с Any
(а также $mod
), могу ли я предложить другой подход? У вас нет информации о типе с Any
Таким образом, вы не можете обойти кастинг во время выполнения (и я не уверен, как рефлексия также поможет вам.) Таким образом, вы не получаете никаких преимуществ от статической системы типов. Вот эскиз того, как вы могли бы реализовать такой метод, используя иерархию типов для обеспечения безопасности типов:
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)
}
}
Кроме того, вы можете определить абстрактный метод выполнения на Query
и переопределить его в каждом расширяющем классе вместо того, чтобы делать match
заявление в parse
, Оттуда вы можете абстрагироваться дальше, используя параметры типа или универсальные типы, чтобы, например, GreaterThan
взять любой Numeric
тип.