2013-03-01 4 views
-1

En tant qu'utilisateur de sous-ensemble, j'aimerais produire une requête contenant deux points, mais je ne la fais pas à la volée. Permettez-moi d'améliorer votre exemple BlogPost http://osinka.github.com/subset/Subset+Query.html pour démontrer ce que je veux atteindre, même si elle n'a pas de sens de cette façon:Comment réaliser la notation par points en cascade MongoDB DBObject via osinka.subset

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 

Comment puis-je produire un dbobject { "comments.text.subText" : "X"}?

Merci, Peter

Répondre

1

Je suis l'auteur de Sous-ensemble, alors laissez-moi une digression et expliquer les détails.

Le sous-ensemble (1.x) fournit Field[T] pour lire et/ou écrire des champs dans/à partir de documents MongoDB (BSON). Lorsque vous lisez ou écrivez le contenu du champ, la seule chose qu'il doit savoir est T. En d'autres termes, si vous travaillez avec des documents BSON, vous pouvez déclarer tous les champs comme "fieldName".fieldOf[T] quel que soit le complexe T (par exemple liste ou sous-document)

Les choses se compliquent dès que vous avez besoin de créer des requêtes. Étant donné que MongoDB prend en charge la "notation par points", Le sous-ensemble doit connaître la relation entre le document parent et les champs descendants. Cet objectif est accompli lorsque vous déclarez les champs "fieldName".subset(Obj).of[T]. Ici, T n'est pas du tout lié à Obj. T est utilisé par Sous-ensemble pour sérialiser/désérialiser le contenu du champ, alors que Obj est simplement un conteneur avec des champs, Le sous-ensemble vous le restitue lorsque vous appelez par ex. Permettez-moi de le démontrer par l'exemple. where

La seule chose que vous devez changer dans votre code est le suivant:

object Comment { 
    ... 
    val text = "text".subset(SubComment).of[SubComment] 
} 

puis vous écririez

scala> val q = BlogPost.comments.where { comment => 
    | comment.text.where { _.text === "X" } 
    | } 
q: com.osinka.subset.package.Query = Query{ "comments.text.text" : "X"} 

Ici, commentest objet Comment.


Quand vous savez cela, vous êtes libre de « tricher » et procédez comme suit:

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"} 

Ici je donne la méthode Unit à .subset() et donc nous obtenons Unit retour dans where. Mais ce n'est pas grave, puisque nous savons quels champs utiliser à l'intérieur where appels. Cette "tricherie" n'est pas aussi "sûre" que de garder des champs à l'intérieur d'objets, mais montre bien comment les choses sont câblées.

+0

Génial! Ça fonctionne et j'aime cela. –

+0

Je suis content d'entendre ça! Acceptez la réponse, s'il vous plaît –

Questions connexes