作为Subset用户,我想生成一个包含两个点的Query,但我不能动态完成。让我改进你的BlogPost示例http://osinka.github.com/subset/Subset+Query.html,以展示我想要实现的目标,即使这样做没有意义:
case class SubComment(subText: String)
case class Comment(by: String, votes: Int, text: SubComment)
case class BlogPost(title: String, comments: List[Comment])
object SubComment {
val text = "text".fieldOf[String]
implicit val writer = {
def f(sub: SubComment): DBObject = (text -> sub.subText)
ValueWriter(f _)
}
}
object Comment {
val by = "by".fieldOf[String]
val votes = "votes".fieldOf[Int]
val text = "text".fieldOf[SubComment]
}
object BlogPost {
val title = "title".fieldOf[String]
val comments = "comments".subset(Comment).of[List[Comment]]
}
val qComment = BlogPost.comments.where { _.by === "maria" }
val qSubComment = BlogPost.comments.where {…? === "X"} // not yet working
如何生成DBObject { "comments.text.subText" : "X"}
?
谢谢, 彼得
答案 0 :(得分:1)
我是 Subset 的作者,所以让我绕道而行,解释一下细节。
子集(1.x)提供Field[T]
来读取和/或写入MongoDB文档(BSON)的字段。当您阅读或撰写该字段的内容时,它唯一必须知道的是T
。换句话说,如果您正在使用BSON文档,则可以将所有字段声明为"fieldName".fieldOf[T]
,无论复杂T
是什么(例如列表或子文档)
只要您需要创建查询,事情就会变得更加复杂。由于MongoDB支持“点表示法”,子集需要知道父文档和后代字段之间的关系。将字段声明为"fieldName".subset(Obj).of[T]
时,此目标即可完成。在这里,T
实际上与Obj
完全无关。 子集使用T
来序列化/反序列化字段内容,而Obj
只是一个包含字段的容器,子集会将其提供给您当你调用例如where
让我举例说明一下。您需要在代码中更改的唯一内容如下:
object Comment {
...
val text = "text".subset(SubComment).of[SubComment]
}
然后你会写
scala> val q = BlogPost.comments.where { comment =>
| comment.text.where { _.text === "X" }
| }
q: com.osinka.subset.package.Query = Query{ "comments.text.text" : "X"}
此处,comment
是 Comment
对象。
当您知道这一点时,您可以“欺骗”并执行以下操作:
val comments = "comments".subset(()).of[List[Comment]]
val commentText = "text".subset(()).of[SubComment]
val subcommentInnerField = "inner".fieldOf[String]
scala> comments.where { _ =>
| commentText.where { _ =>
| subcommentInnerField === "X"
| }
| }
res1: com.osinka.subset.package.Query = Query{ "comments.text.inner" : "X"}
在这里,我将Unit
提供给.subset()
方法,因此我们将Unit
带回where
。但这没关系,因为我们知道在where
调用中使用哪些字段。这种“作弊”并不像保持对象内的字段那样“安全”,但很好地展示了事物的连线方式。