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] },
...
]
}
Основната предпоставка тук е, че съм вложил Comments
вътре в Article
. Votes
се прилага само към Comment
, така че те са били съхранени като масив с всеки Comment
. В този случай току-що съхраних user_id. Ако искате да съхранявате повече информация (time_created и т.н.), тогава можете да гласувате за масив от обекти:
... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ...
Как да изпълнявате заявките си ефективно:
db.articles.find( { _id : 'A' } )
Това получава всичко с една заявка. Може да се наложи да направите някаква логика от страна на клиента, за да преброите гласовете за коментар, но това е доста тривиално.
db.articles.ensureIndex( { "comments.user_id" : 1 } )
db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
Индексът ще позволи ефективно търсене на коментари в рамките на документ.
Понастоящем няма начин да се извлекат само съвпаденията от подмасив. Тази заявка всъщност ще върне всички статии с коментари от този потребител. Ако това е потенциално твърде много данни, можете да направите известно изрязване.
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 } )
Отново това ще върне всички статии, а не само коментарите.
Тук трябва да се направи компромис. Връщането на статията може да изглежда, че връщаме твърде много данни. Но какво планирате да покажете на потребителя, когато направите заявка #3?
Получаване на списък с „коментари, за които съм гласувал“ не е много полезно без самия коментар. Разбира се, коментарът не е много полезен без самата статия (или поне само заглавието).
През по-голямата част от времето заявка #3 се превръща в обединяване от Votes
към Comments
към Articles
. Ако случаят е такъв, тогава защо просто не върнете статиите като начало?