これが私のコードです。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 }
フォールディング操作ごとにこれら2つのオブジェクトの新しいインスタンスを作成するのではなく、TypesafeMongoQuery[Nothing]
構築される基礎となるDBObjectが常に同じであるため、タイプのval /シングルトンを使用することは可能だと思います。
署名を至る所で置き換えるなど、いくつかのことを試しました[ObjectType,T <% ObjectType]
が、大きな成功はありませんでした。
私の問題を解決する方法について何か考えはありますか?