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 тип.

Другие вопросы по тегам