2017-01-04 17 views
5

Tôi đang làm việc trên một ứng dụng thực hiện điều gì đó tương tự như star count on a blog post example được đưa ra trong tài liệu Firebase và tôi có câu hỏi về thiết kế của hệ thống bỏ phiếu và có sử dụng hay không.Thiết kế phù hợp của hệ thống gắn dấu sao/thích trong Firebase: Tôi có nên sử dụng giao dịch không?

Từ ví dụ này, các dữ liệu cho một bài trông như thế này:

postid { 
    // some data here about the post, author, id, etc, 
    starCount : <an integer count of the stars>, 
    stars : { 
     <user who starred> : true, 
     <user who starred> : true, 
     // ... and so on, basically a list of all the users who starred the post 
    } 
} 

Các tài liệu sử dụng một giao dịch để cập nhật các sao đếm:

private void onStarClicked(DatabaseReference postRef) { 
    postRef.runTransaction(new Transaction.Handler() { 
     @Override 
     public Transaction.Result doTransaction(MutableData mutableData) { 
      Post p = mutableData.getValue(Post.class); 
      if (p == null) { 
       return Transaction.success(mutableData); 
      } 

      if (p.stars.containsKey(getUid())) { 
       // Unstar the post and remove self from stars 
       p.starCount = p.starCount - 1; 
       p.stars.remove(getUid()); 
      } else { 
       // Star the post and add self to stars 
       p.starCount = p.starCount + 1; 
       p.stars.put(getUid(), true); 
      } 

      // Set value and report transaction success 
      mutableData.setValue(p); 
      return Transaction.success(mutableData); 
     } 

     @Override 
     public void onComplete(DatabaseError databaseError, boolean b, 
           DataSnapshot dataSnapshot) { 
      // Transaction completed 
      Log.d(TAG, "postTransaction:onComplete:" + databaseError); 
     } 
    }); 
} 

Bởi vì việc sử dụng một giao dịch cả số starCountstars dường như cần là một phần của cùng một đối tượng. Tại sao? Bởi vì tôi muốn sử dụng cả một giao dịch và đảm bảo tính tự động. Các tùy chọn khác để đảm bảo tính tự động là cập nhật đa đường dẫn, nhưng như được ghi chú here in the comments bạn không thể sử dụng cập nhật đa đường dẫn với các hiệu ứng chuyển tiếp. Bạn có quyền truy cập vào mutableData (trong trường hợp này là đối tượng bài đăng) và đó là nó.

SO nếu starCountstars phải được lưu trữ ở cùng một vị trí, Tôi không hiểu điểm của starCount. Bất cứ khi nào bạn nhận được một đối tượng bài đăng, nó sẽ bao gồm stars, danh sách những người đã gắn dấu sao nó. Tại sao không xóa hoàn toàn starCount và chỉ nhận được kích thước của danh sách sao? Có điều gì đó không thực hiện về điều này?

Trong trường hợp này, gắn dấu sao/bỏ gắn dấu sao gì đó sẽ giống như p.stars.put(getUid(), true);p.stars.remove(getUid());. Nếu tôi đã làm điều đó, tôi không thấy sự cần thiết cho một giao dịch, bởi vì tôi không còn có nhiều người dùng cập nhật một đối tượng "phản đối". Tôi có thể sử dụng giao dịch cho tuyên bố p.stars.put(getUid(), true);, nhưng dường như không chắc với tôi rằng cùng một người dùng cố gắng gắn dấu sao/bỏ gắn dấu sao từ hai thiết bị khác nhau và thậm chí nếu họ làm như vậy, nó sẽ không bị ảnh hưởng nhiều đến mức tôi có thể nói.

Vì vậy, tôi thiếu gì ở đây? Tại sao sử dụng giao dịch tại đây và lợi ích nào lưu trữ và theo dõi theo cách thủ công starCount thêm? Tôi có thể thấy một lợi ích hiệu suất lưu trữ danh sách người dùng stars ở nơi khác trong cơ sở dữ liệu, như được hiển thị trong this example, nhưng sau đó giao dịch sẽ không hoạt động.

Bất kỳ thông tin chi tiết nào sẽ được đánh giá cao và cảm ơn bạn!

Trả lời

0

Trong nỗ lực của chúng tôi để tạo một ứng dụng mẫu hoạt động đơn lẻ để lấy mẫu tài liệu, chúng tôi thực sự đã tạo ra việc sử dụng không hợp lý (nhưng chức năng) cho các giao dịch.

Tôi khuyên bạn nên xem my answer to this question để có cách tính hợp lý hơn (nhưng chắc chắn phức tạp) khi tính số lượng bảo mật bằng cách sử dụng cập nhật nhiều vị trí và quy tắc bảo mật phía máy chủ.

Nói chung, tôi luôn khuyên bạn nên tách logic biểu quyết khỏi logic đếm trong các trường hợp như thế này. Vì vậy, khi một phiếu sử dụng cho một bài đăng, bạn viết một kỷ lục đơn giản vào cơ sở dữ liệu ghi lại hành động của họ:

votesQueue 
    <push id> 
     <uid>: true 

Và sau đó bạn có một kịch bản máy chủ nhỏ (ví dụ như một firebase queue worker) mà nghe đến hàng đợi này và tập hợp các số phiếu bầu.

Cách tiếp cận này rất phổ biến khi sử dụng Firebase và làm cho các vấn đề đơn giản hơn rất nhiều. Bạn có thể dễ dàng tưởng tượng cách bạn sẽ bảo đảm hai nút này (votesQueuevoteTotals), trong khi tôi có thể đảm bảo với bạn rằng giải pháp trong câu trả lời tôi đã liên kết ở trên mang lại cho tôi một số vấn đề về bảo trì.

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