【问题标题】:Scala casbah DSL queriesScala casbah DSL 查询
【发布时间】:2013-09-18 01:42:56
【问题描述】:

我正在学习 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 作为地图的值并获取第一项和第二项吗?

【问题讨论】:

    标签: mongodb scala casbah


    【解决方案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 上定义一个抽象执行方法并在每个扩展类中覆盖它,而不是在parse 中执行match 语句。从那里,您可以使用类型参数或泛型类型进一步抽象,以允许 GreaterThan 采用任何 Numeric 类型。

    【讨论】:

    • 更好的方法。但是我仍然必须将我的 Any 转换为一种类型。我正在使用这个 Map[String,Any] 因为我正在使用 scala 本机解析器解析 JSON。它给了我一个 Map[String, Any],所以我必须将这个 Any 转换为正确的类型。我考虑过反射来检查它的类型并以正确的演员阵容返回。关于 $regex 问题,我在文档中使用了指向我使用 SBT 的教程,所以我认为它下载了最新的 jar。我浏览了 jar 并在那里找到了 $regex 函数......我不知道为什么编译器会抱怨这个
    • 如果您可以控制 JSON 消息格式,则可以使用 json4s (github.com/json4s/json4s) 轻松序列化和反序列化案例类。即使您不这样做,使用该库您也可以提取查询类型,然后进行相应的反序列化。
    • 再次嗨...我正在尝试他们的 website 中的示例,但我总是收到错误(格式错误的类名)
    • 我是用 Lift-json 做的。但是我还是有一个疑问,像 $eq 这样支持多种 Types 的情况下,我该如何解决这个问题呢?我不能有两个同名的类。所以我不能有一个 Eq(field:String, value: Int) 和一个 Eq(field:string, value:String)
    • 类可以任意命名。如果你感觉特别先进,你可以看看 casbah 库作者是如何处理这个问题的,因为它是开源的:github.com/mongodb/casbah/blob/master/casbah-query/src/main/…github.com/mongodb/casbah/blob/master/casbah-query/src/main/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    • 2017-09-18
    相关资源
    最近更新 更多