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] },
...
]
}
Den grundlæggende forudsætning her er, at jeg har indlejret Comments
inde i Article
. Votes
gælder kun for en Comment
, så de er blevet gemt som et array med hver Comment
. I dette tilfælde har jeg lige gemt user_id. Hvis du vil gemme mere information (time_created osv.), så kan du stemme på en række objekter:
... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ...
Sådan udfører du dine forespørgsler effektivt:
db.articles.find( { _id : 'A' } )
Dette får alt med én forespørgsel. Du skal muligvis lave noget logik på klientsiden for at tælle stemmer pr. kommentar, men det er ret trivielt.
db.articles.ensureIndex( { "comments.user_id" : 1 } )
db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
Indekset giver mulighed for effektivt at søge i kommentarerne i et dokument.
Der er i øjeblikket ingen måde kun at udtrække matches fra et underarray. Denne forespørgsel vil faktisk returnere alle artikler med kommentarer fra den pågældende bruger. Hvis dette potentielt er alt for mange data, kan du trimme lidt.
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 } )
Igen vil dette returnere alle artiklerne, ikke kun kommentarerne.
Der er en afvejning her. At returnere artiklen kan virke som om, at vi bringer for mange data tilbage. Men hvad planlægger du at vise til brugeren, når du laver forespørgsel #3?
Få en liste over "kommentarer, jeg har stemt på" er ikke særlig nyttigt uden selve kommentaren. Naturligvis er kommentaren ikke særlig brugbar uden selve artiklen (eller i det mindste kun titlen).
Det meste af tiden overgår forespørgsel #3 til en joinforbindelse fra Votes
til Comments
til Articles
. Hvis det er tilfældet, hvorfor så ikke bare bringe artiklerne tilbage til at begynde med?