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] },
...
]
}
Podstawowym założeniem jest to, że zagnieździłem Comments
wewnątrz Article
. Votes
stosuje się tylko do Comment
, więc zostały zapisane jako tablica z każdym Comment
. W tym przypadku właśnie zapisałem user_id. Jeśli chcesz przechowywać więcej informacji (time_created itp.), możesz głosować na tablicę obiektów:
... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ...
Jak skutecznie wykonywać zapytania:
db.articles.find( { _id : 'A' } )
To dostaje wszystko za pomocą jednego zapytania. Być może będziesz musiał zastosować logikę po stronie klienta, aby policzyć głosy na komentarz, ale jest to dość trywialne.
db.articles.ensureIndex( { "comments.user_id" : 1 } )
db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
Indeks pozwoli na sprawne wyszukiwanie komentarzy w dokumencie.
Obecnie nie ma możliwości wyodrębnienia tylko dopasowań z podtablicy. To zapytanie w rzeczywistości zwróci wszystkie artykuły z komentarzami tego użytkownika. Jeśli to potencjalnie za dużo danych, możesz trochę przyciąć.
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 } )
Ponownie, spowoduje to zwrócenie wszystkich artykułów, a nie tylko komentarzy.
Tutaj należy dokonać kompromisu. Zwracanie artykułu może wydawać się, że zwracamy za dużo danych. Ale co planujesz wyświetlić użytkownikowi podczas tworzenia zapytania nr 3?
Pobieranie listy „komentarzy, na które głosowałem” nie jest strasznie przydatne bez samego komentarza. Oczywiście komentarz nie jest zbyt przydatny bez samego artykułu (a przynajmniej samego tytułu).
W większości przypadków zapytanie #3 przechodzi w sprzężenie z Votes
do Comments
do Articles
. Jeśli tak jest, to dlaczego nie przywrócić artykułów na początek?