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] },
...
]
}
A premissa básica aqui é que eu aninhei os
Comments
dentro do Article
. Os Votes
aplicam-se apenas a um Comment
, então eles foram armazenados como uma matriz com cada Comment
. Nesse caso, acabei de armazenar o user_id. Se você quiser armazenar mais informações (time_created, etc.), poderá votar em uma matriz de objetos:... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ...
Como realizar suas consultas com eficiência:
db.articles.find( { _id : 'A' } )
Isso obtém tudo com uma consulta. Você pode ter que fazer alguma lógica do lado do cliente para contar votos por comentário, mas isso é bastante trivial.
db.articles.ensureIndex( { "comments.user_id" : 1 } )
db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
O índice permitirá uma busca eficiente dos comentários dentro de um documento.
Atualmente, não há como extrair apenas as correspondências de uma sub-matriz. Esta consulta de fato retornará todos os artigos com comentários desse usuário. Se isso for potencialmente muitos dados, você pode fazer alguns cortes.
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 } )
Novamente, isso retornará todos os artigos, não apenas os comentários.
Há uma troca a ser feita aqui. Devolver o artigo pode parecer que estamos trazendo muitos dados de volta. Mas o que você pretende exibir para o usuário quando fizer a consulta nº 3?
Obtendo uma lista de "comentários nos quais votei" não é muito útil sem o comentário em si. Claro que o comentário não é muito útil sem o próprio artigo (ou pelo menos apenas o título).
Na maioria das vezes, a consulta nº 3 se transforma em uma junção de
Votes
para Comments
para Articles
. Se for esse o caso, então por que não trazer de volta os Artigos para começar?