Article {
"_id" : "A",
"title" : "Hello World",
"user_id" : 12345,
"text" : 'My test article',
"comments" : [
{ 'text' : 'blah', 'user_id' : 654321, 'votes' : [987654]},
{ 'text' : 'foo', 'user_id' : 987654, 'votes' : [12345, 654321] },
...
]
}
Le principe de base ici est que j'ai imbriqué les Comments
à l'intérieur de l'Article
. Les Votes
ne s'applique qu'à un Comment
, ils ont donc été stockés sous forme de tableau avec chaque Comment
. Dans ce cas, je viens de stocker le user_id. Si vous souhaitez stocker plus d'informations (time_created, etc.), vous pouvez voter sur un tableau d'objets :
... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ...
Comment effectuer vos requêtes efficacement :
db.articles.find( { _id : 'A' } )
Cela obtient tout avec une seule requête. Vous devrez peut-être appliquer une certaine logique côté client pour compter les votes par commentaire, mais c'est assez trivial.
db.articles.ensureIndex( { "comments.user_id" : 1 } )
db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
L'index permettra de rechercher efficacement les commentaires dans un document.
Il n'existe actuellement aucun moyen d'extraire uniquement les correspondances d'un sous-tableau. Cette requête renverra en fait tous les articles avec des commentaires de cet utilisateur. Si c'est potentiellement beaucoup trop de données, vous pouvez faire quelques ajustements.
db.articles.find( { "comments.user_id" : 987654 }, { "title" : 1, "comments.user_id" : 1 })
db.articles.ensureIndex( { "comments.votes" : 1 } )
db.articles.find( { "comments.votes" : 987654 } )
Encore une fois, cela renverra tous les articles, pas seulement les commentaires.
Il y a un compromis à faire ici. Rendre l'article peut donner l'impression que nous ramenons trop de données. Mais qu'envisagez-vous d'afficher à l'utilisateur lorsque vous effectuez la requête #3 ?
Obtenir une liste de "commentaires pour lesquels j'ai voté" n'est pas très utile sans le commentaire lui-même. Bien sûr, le commentaire n'est pas très utile sans l'article lui-même (ou du moins juste le titre).
La plupart du temps, la requête #3 se transforme en une jointure à partir de Votes
vers Comments
vers Articles
. Si tel est le cas, pourquoi ne pas simplement ramener les articles pour commencer ?