Trước hết, 'Từ điển trong Lớp người dùng' không phải là một ý kiến hay. tại sao? Việc thêm đối tượng tỷ lệ bổ sung yêu cầu đẩy một mục mới vào mảng, điều này có nghĩa là mục cũ sẽ bị xóa và phần chèn này được gọi là " di chuyển tài liệu ". Việc di chuyển tài liệu rất chậm và MongoDB không sử dụng lại không gian trống rất tuyệt vời, vì vậy việc di chuyển tài liệu nhiều nơi có thể dẫn đến nhiều tệp dữ liệu trống (một số văn bản trong sách 'MongoDB The Definitive Guide').
Sau đó, giải pháp chính xác là gì:giả sử bạn có một bộ sưu tập có tên Blog và muốn triển khai giải pháp xếp hạng cho các bài đăng trên blog của mình và theo dõi thêm mọi hoạt động xếp hạng dựa trên người dùng.
Lược đồ cho một tài liệu blog sẽ giống như sau:
{
_id : ....,
title: ....,
....
rateCount : 0,
rateValue : 0,
rateAverage: 0
}
Bạn cần một bộ sưu tập khác (Giá) với giản đồ tài liệu này:
{
_id: ....,
userId: ....,
postId:....,
value: ..., //1 to 5
date:....
}
Và bạn cần xác định một chỉ mục thích hợp cho nó:
db.Rates.ensureIndex({userId : 1, postId : 1})// very useful. it will result in a much faster search operation in case you want to check if a user has rated the post previously
Khi người dùng muốn đánh giá, trước hết bạn cần kiểm tra xem người dùng đã đánh giá bài viết đó hay chưa. giả sử người dùng là 'user1'
, truy vấn sau đó sẽ là
var ratedBefore = db.Rates.find({userId : 'user1', postId : 'post1'}).count()
Và dựa trên ratedBefore
, nếu !ratedBefore
sau đó chèn tài liệu tỷ giá mới vào bộ sưu tập Tỷ lệ và cập nhật trạng thái blog, nếu không, người dùng không được phép xếp hạng
if(!ratedBefore)
{
var postId = 'post1'; // this id sould be passed before by client driver
var userId = 'user1'; // this id sould be passed before by client driver
var rateValue = 1; // to 5
var rate =
{
userId: userId,
postId: postId,
value: rateValue,
date:new Date()
};
db.Rates.insert(rate);
db.Blog.update({"_id" : postId}, {$inc : {'rateCount' : 1, 'rateValue' : rateValue}});
}
Sau đó, điều gì sẽ xảy ra với rateAverage
? Tôi thực sự khuyên bạn nên tính toán nó dựa trên rateCount
và rateValue
về phía máy khách, có thể dễ dàng cập nhật rateAverage
với mongoquery
, nhưng bạn không nên làm điều đó. tại sao? Câu trả lời đơn giản là:đây là một công việc rất dễ dàng cho khách hàng để xử lý những loại công việc này và việc đặt mức trung bình cho mọi tài liệu blog cần một thao tác cập nhật không cần thiết.
truy vấn trung bình sẽ được tính là:
var blog = db.Blog.findOne({"_id" : "post1"});
var avg = blog.rateValue / blog.rateCount;
print(avg);
Với cách tiếp cận này, bạn sẽ nhận được hiệu suất tối đa với mongodb mà bạn có thể theo dõi mọi tỷ lệ dựa trên người dùng, bài đăng và ngày.