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] },
...
]
}
Tiền đề cơ bản ở đây là tôi đã lồng các Comments
bên trong Article
. Votes
chỉ áp dụng cho một Comments
, vì vậy chúng đã được lưu trữ dưới dạng một mảng với mỗi Comments
. Trong trường hợp này, tôi vừa lưu trữ user_id. Nếu bạn muốn lưu trữ nhiều thông tin hơn (time_create, v.v.), thì bạn có thể bỏ phiếu cho một mảng các đối tượng:
... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ...
Cách thực hiện các truy vấn của bạn một cách hiệu quả:
db.articles.find( { _id : 'A' } )
Điều này nhận được mọi thứ với một truy vấn. Bạn có thể phải thực hiện một số logic phía khách hàng để đếm số phiếu bầu cho mỗi nhận xét, nhưng điều này khá nhỏ.
db.articles.ensureIndex( { "comments.user_id" : 1 } )
db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
Chỉ mục sẽ cho phép tìm kiếm hiệu quả các nhận xét trong tài liệu.
Hiện tại không có cách nào để chỉ trích xuất các kết quả phù hợp từ một mảng con. Trên thực tế, truy vấn này sẽ trả về tất cả các bài báo có nhận xét của người dùng đó. Nếu cách này có khả năng là quá nhiều dữ liệu, bạn có thể thực hiện một số thao tác cắt bớt.
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 } )
Một lần nữa, điều này sẽ trả về tất cả các Bài báo, không chỉ các nhận xét.
Có một sự đánh đổi phải được thực hiện ở đây. Việc trả lại bài báo có vẻ như chúng tôi đang trả lại quá nhiều dữ liệu. Nhưng bạn định hiển thị điều gì cho người dùng khi thực hiện truy vấn số 3?
Nhận danh sách "nhận xét mà tôi đã bình chọn" không hữu ích khủng khiếp nếu không có nhận xét chính nó. Tất nhiên nhận xét không hữu ích lắm nếu không có chính bài viết (hoặc ít nhất chỉ là tiêu đề).
Hầu hết thời gian, truy vấn số 3 chuyển thành một liên kết từ Votes
đến Comments
tới Articles
. Nếu đúng như vậy, tại sao không quay lại các Bài báo để bắt đầu?