0

这是我的代码。它允许使用 Casbah 创建类型安全的 MongoDB 查询

trait TypesafeQuery[ObjectType, BuildType] {

  def build: BuildType

}

trait TypesafeMongoQuery[ObjectType] extends TypesafeQuery[ObjectType, DBObject]

case class TypesafeMongoQueryConjunction[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) extends TypesafeMongoQuery[ObjectType] {
  override def build(): DBObject = $and(queries.map(_.build))
}

case class TypesafeMongoQueryDisjunction[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) extends TypesafeMongoQuery[ObjectType] {
  override def build(): DBObject = $or(queries.map(_.build))
}

object TypesafeMongoQuery {

  // TODO could probably be reworked? see http://stackoverflow.com/questions/23917459/best-way-to-create-a-mongo-expression-that-never-matches
  val AlwaysMatchingQuery: DBObject = $()
  val NeverMatchingQuery: DBObject = $and($("_id" -> 1), $("_id" -> -1))

  def AlwaysMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = AlwaysMatchingQuery }
  def NeverMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = NeverMatchingQuery }

  def and[ObjectType](queries: TypesafeMongoQuery[ObjectType]*) = TypesafeMongoQueryConjunction(queries)
  def or[ObjectType](queries: TypesafeMongoQuery[ObjectType]*) = TypesafeMongoQueryDisjunction(queries)

  // TODO maybe define Scalaz Monoids

  def foldAnd[ObjectType](queries: Seq[TypesafeMongoQuery[ObjectType]]) = {
    queries.foldLeft(AlwaysMatchingTypesafeQuery[ObjectType]) { (currentQuery, queryInList) =>
      TypesafeMongoQuery.and(currentQuery, queryInList)
    }
  }
  def foldOr[ObjectType](base: TypesafeMongoQuery[ObjectType], queries: Seq[TypesafeMongoQuery[ObjectType]]) = {
    queries.foldLeft(NeverMatchingTypesafeQuery[ObjectType]) { (currentQuery, queryInList) =>
      TypesafeMongoQuery.or(currentQuery, queryInList)
    }
  }

}

它工作正常,除了我对这些行不满意:

  def AlwaysMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = AlwaysMatchingQuery }
  def NeverMatchingTypesafeQuery[ObjectType] = new TypesafeMongoQuery[ObjectType] { override def build(): DBObject = NeverMatchingQuery }

我认为可以不为每个折叠操作创建这两个对象的新实例,而是使用 val / singleton 类型TypesafeMongoQuery[Nothing],因为正在构建的底层 DBObject 总是相同的。

我已经尝试了一些事情,比如到处替换我的签名,[ObjectType,T <% ObjectType]但没有取得很大的成功。

关于如何解决我的问题的任何想法?

4

1 回答 1

0

你能做ObjectType协变吗?

trait TypesafeQuery[+ObjectType, BuildType] {

  def build: BuildType

}

trait TypesafeMongoQuery[+ObjectType] extends TypesafeQuery[+ObjectType, DBObject]

object AlwaysMatchingTypesafeQuery extends TypesafeMongoQuery[Nothing] { override def build(): DBObject = AlwaysMatchingQuery }
object NeverMatchingTypesafeQuery extends TypesafeMongoQuery[Nothing] { override def build(): DBObject = NeverMatchingQuery }
于 2014-06-13T21:34:07.800 回答