2015-01-18 20 views
9

Hiện tại tôi đang làm việc trên một ứng dụng dành cho thiết bị di động. Về cơ bản mọi người có thể đăng ảnh của họ và những người theo dõi có thể thích những bức ảnh như Instagram. Tôi sử dụng mongodb làm cơ sở dữ liệu. Giống như instagram, có thể có rất nhiều lượt thích cho một ảnh. Vì vậy, việc sử dụng một tài liệu cho một đơn "like" với chỉ mục có vẻ không hợp lý vì nó sẽ lãng phí rất nhiều bộ nhớ. Tuy nhiên, tôi muốn một người dùng thêm một cách nhanh chóng. Vì vậy, câu hỏi của tôi là làm thế nào để mô hình "như"? Về cơ bản mô hình dữ liệu tương tự như instagram nhưng sử dụng Mongodb.Cách tạo mô hình hệ thống bỏ phiếu "thích" với MongoDB

+0

Bạn có thể có trường 'thích' cho mỗi tài liệu tat điểm vào ảnh. và sử dụng toán tử '$ inc' để cập nhật trường cho mỗi tài liệu theo cách nguyên tử. Nhưng nếu bạn có thể đăng cấu trúc tài liệu hiện tại của bạn và cụm từ lại yêu cầu của bạn đúng cách, bạn sẽ nhận được câu trả lời tốt. – BatScream

+2

Thêm lượt thích sẽ cực kỳ dễ dàng và nhanh chóng, bạn có thể chuyển tất cả dữ liệu cần thiết thẳng đến máy chủ và thực hiện một truy vấn để chèn thẳng vào DB. Tuy nhiên, bạn sẽ wan để bộ nhớ cache và tổng hợp như đếm kể từ khi đếm những người thích sẽ khó chịu. Hầu hết các trang web, kể cả instagram, sử dụng bộ đếm, như @BatScream cho biết sử dụng $ inc (hoặc bất kỳ thứ gì tồn tại trong công nghệ mà họ đang sử dụng) để lưu vào bộ nhớ cache, giúp dễ dàng nói số lượt thích có một số câu trả lời là – Sammaye

Trả lời

23

Không có vấn đề làm thế nào bạn cấu trúc tài liệu tổng thể của bạn về cơ bản có hai điều bạn cần. Đó là cơ bản một tài sản bốn "đếm" và "danh sách" của những người đã đăng ở đó "như" để đảm bảo không có bản sao được gửi. Dưới đây là một cấu trúc cơ bản:

{ 
    "_id": ObjectId("54bb201aa3a0f26f885be2a3") 
    "photo": "imagename.png", 
    "likeCount": 0 
    "likes": [] 
} 

Dù vậy, có một "_id" độc đáo cho "bài ảnh" của bạn và bất kỳ thông tin mà bạn muốn, nhưng sau đó các lĩnh vực khác như đã đề cập. Thuộc tính "thích" ở đây là một mảng và nó sẽ giữ các giá trị "_id" duy nhất từ ​​các đối tượng "người dùng" trong hệ thống của bạn. Vì vậy, mọi "người dùng" đều có mã định danh duy nhất của riêng họ ở đâu đó, trong bộ nhớ cục bộ hoặc OpenId hoặc thứ gì đó, nhưng là một số nhận dạng duy nhất. Tôi sẽ gắn bó với ObjectId cho ví dụ.

Khi ai đó gửi một "như" một bài viết, bạn muốn phát hành báo cáo cập nhật sau:

db.photos.update(
    { 
     "_id": ObjectId("54bb201aa3a0f26f885be2a3"), 
     "likes": { "$ne": ObjectId("54bb2244a3a0f26f885be2a4") } 
    }, 
    { 
     "$inc": { "likeCount": 1 }, 
     "$push": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") } 
    } 
) 

Bây giờ hoạt động $inc có sẽ làm tăng giá trị của "likeCount" bởi số lượng quy định, vì vậy tăng thêm 1. Thao tác $push thêm số nhận dạng duy nhất cho người dùng vào mảng trong tài liệu để tham khảo trong tương lai.

Điều quan trọng nhất ở đây là lưu giữ hồ sơ của những người dùng đã bỏ phiếu và những gì đang xảy ra trong phần "truy vấn" của tuyên bố. Ngoài việc chọn tài liệu để cập nhật bởi "_id" duy nhất của riêng nó, điều quan trọng khác là kiểm tra mảng "thích" để đảm bảo người dùng bỏ phiếu hiện tại không có trong đó.

Điều này cũng đúng đối với trường hợp ngược lại hay "loại bỏ" các "like":

db.photos.update(
    { 
     "_id": ObjectId("54bb201aa3a0f26f885be2a3"), 
     "likes": ObjectId("54bb2244a3a0f26f885be2a4") 
    }, 
    { 
     "$inc": { "likeCount": -1 }, 
     "$pull": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") } 
    } 
) 

Điều quan trọng chính ở đây là các điều kiện truy vấn được sử dụng để đảm bảo rằng không có tài liệu được chạm nếu tất cả các điều kiện không được đáp ứng. Vì vậy, số lượng không tăng nếu người dùng đã bỏ phiếu hoặc giảm nếu phiếu bầu của họ không thực sự có mặt tại thời điểm cập nhật.

Tất nhiên việc đọc một mảng với vài trăm mục trong tài liệu trở lại trong bất kỳ phần nào khác của ứng dụng là không thực tế. Nhưng MongoDB có một cách rất tiêu chuẩn để xử lý đó cũng như:

db.photos.find(
    { 
     "_id": ObjectId("54bb201aa3a0f26f885be2a3"), 
    }, 
    { 
     "photo": 1 
     "likeCount": 1, 
     "likes": { 
      "$elemMatch": { "$eq": ObjectId("54bb2244a3a0f26f885be2a4") } 
     } 
    } 
) 

sử dụng này $elemMatch trong bản dự báo sẽ chỉ trả lại cho người dùng hiện tại nếu họ có mặt hay chỉ là một mảng trống nơi họ thì không. Điều này cho phép phần còn lại của logic ứng dụng của bạn được biết nếu người dùng hiện tại đã đặt phiếu bầu hay không.

Đó là kỹ thuật cơ bản và có thể phù hợp với bạn, nhưng bạn nên lưu ý rằng các mảng nhúng không nên mở rộng vô hạn và cũng có giới hạn 16MB cứng đối với tài liệu BSON. Vì vậy, khái niệm là âm thanh, nhưng chỉ không thể được sử dụng trên riêng của nó nếu bạn đang mong đợi 1000 của "như phiếu bầu" về nội dung của bạn.Có một khái niệm được gọi là "bucketing" được thảo luận chi tiết trong ví dụ này cho Hybrid Schema design cho phép một giải pháp lưu trữ một lượng lớn "lượt thích". Bạn có thể xem điều đó để sử dụng cùng với các khái niệm cơ bản ở đây như một cách để làm điều này ở mức âm lượng.

+1

. điều này lên nhưng ý tưởng của bạn về việc triển khai một giải pháp như thế này (thay vì sử dụng tài liệu phụ để giữ các lượt thích hoặc phiếu bầu) http://stackoverflow.com/questions/26914380/schema-for-user-ratings-key-value-db – Disposer

+0

@Disposer ý tưởng chung ở đây là để làm cho nó càng đơn giản càng tốt để kiểm tra xem ai đó đã bỏ phiếu hay không và đọc lại tổng số phiếu bầu với tổng hợp hoặc ít nhất bằng cách chia nhỏ thành các tài liệu ít nhất có thể. Các mô hình khác hoặc dựa vào tập hợp trong thời gian thực hoặc bằng cách khác không phải là nguyên tử trong các bản cập nhật. Viết nhanh và đọc nhanh. Đối với các mục hoạt động cao thường là những gì bạn muốn. –

+0

@Neil Lunn. Cảm ơn câu trả lời của bạn. Trên thực tế, cấu trúc dữ liệu của tôi rất giống với cấu trúc dữ liệu của bạn và tôi dự định sử dụng thiết kế thay đổi. Tôi đã tự hỏi làm thế nào tốt là hiệu suất của tìm kiếm rất nhiều xô thích bằng cách sử dụng toán tử $ elemMatch. Giả sử có 30,0000 lượt thích ảnh, tôi có 300 nhóm và mỗi nhóm chứa 1000 lượt thích. Có hiệu quả để biết liệu người dùng hiện tại đã đặt phiếu bầu hay chưa? Và tôi cũng quan tâm đến "Các mô hình khác hoặc dựa vào tập hợp trong thời gian thực" bạn đã đề cập, u có thể giải thích thêm để tôi có thể đánh giá nhiều tùy chọn hơn không? – user2914635

Các vấn đề liên quan