2013-09-18 3 views
0

Я изучаю Скала и пытаюсь Монго тоже. Я создаю функцию, которая принимает Map[String, Any] в качестве параметра, и я хотел бы вернуть надлежащее MongoDBObject для него:Scala casbah DSL-запросы

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 - это проблема, вы столкнетесь со всеми из следующие звонки.

Для вопроса с 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.

+0

Гораздо лучше aproach. Но все же мне придется отбросить мой Any на тип. Я использую эту карту [String, Any], потому что я разбираю JSON, используя собственные синтаксические анализаторы scala. И это дает мне карту [String, Any], поэтому мне придется отнести это Any к соответствующему типу. Я подумал о рефлексии, чтобы проверить тип, который он есть, и вернуть его с правильным приведением. О проблеме $ regex, я использовал учебник в документах, которые указывают мне на использование SBT, поэтому я думаю, что он загрузил последнюю банку. Я прошел через банку и нашел там функцию $ regex ... Я понятия не имею, почему компилятор жалуется на это – Augusto

+1

Если у вас есть контроль над форматом сообщений JSON, вы можете использовать json4s (https://github.com/json4s/json4s) для сериализации и десериализации классов классов. Даже если вы этого не сделаете, используя эту библиотеку, вы можете извлечь тип запроса и затем десериализовать соответственно. –

+1

спасибо. это будет работать :) – Augusto

Смежные вопросы