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] },
...
]
}
Het uitgangspunt hier is dat ik de Comments
. heb genest binnenkant van het Article
. De Votes
alleen van toepassing op een Comment
, dus ze zijn opgeslagen als een array bij elke Comment
. In dit geval heb ik zojuist de user_id opgeslagen. Als u meer informatie wilt opslaan (time_created, enz.), dan kunt u stemmen op een reeks objecten:
... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ...
Hoe u uw zoekopdrachten efficiënt kunt uitvoeren:
db.articles.find( { _id : 'A' } )
Dit krijgt alles met één query. Je moet misschien wat logica aan de clientzijde gebruiken om stemmen per reactie te tellen, maar dit is vrij triviaal.
db.articles.ensureIndex( { "comments.user_id" : 1 } )
db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
De index maakt het mogelijk om de opmerkingen in een document efficiënt te doorzoeken.
Er is momenteel geen manier om alleen de overeenkomsten uit een subarray te extraheren. Deze zoekopdracht zal in feite alle artikelen retourneren met opmerkingen van die gebruiker. Als dit mogelijk veel te veel gegevens zijn, kun je wat bijsnijden.
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 } )
Nogmaals, hiermee worden alle artikelen geretourneerd, niet alleen de opmerkingen.
Hier moet een afweging worden gemaakt. Het retourneren van het artikel kan lijken alsof we te veel gegevens terughalen. Maar wat ben je van plan om aan de gebruiker te laten zien wanneer je vraag #3 doet?
Een lijst krijgen met "opmerkingen waar ik op heb gestemd" is niet erg nuttig zonder de opmerking zelf. Natuurlijk is de opmerking niet erg nuttig zonder het artikel zelf (of in ieder geval alleen de titel).
Meestal gaat vraag 3 over in een join van Votes
naar Comments
naar Articles
. Als dat het geval is, waarom breng je dan niet gewoon de artikelen terug om mee te beginnen?