2011-11-24 27 views
7

Tôi đang cố gắng quyết định phương pháp tốt nhất cho CouchApp (không có phần mềm trung gian). Vì có những điểm tương đồng với ý tưởng của tôi, giả sử chúng ta có một trang stackoverflow được lưu trữ trong CouchDB. Về bản chất nó bao gồm các câu hỏi thực tế trên đầu trang, câu trả lời và hoa hồng. Đó là cơ bản ba lớp.CouchDB: Tài liệu đơn lẻ và tài liệu "ghép nối" với nhau

Có hai cách để lưu trữ. Hoặc trong một tài liệu chứa biểu diễn JSON phù hợp của dữ liệu hoặc lưu trữ từng phần của mục nhập trong một tài liệu riêng biệt kết hợp chúng sau này qua một chế độ xem (tương tự như sau: http://www.cmlenz.net/archives/2007/10/couchdb-joins)

Bây giờ, cả hai cách tiếp cận có thể ổn, nhưng cả hai đều có nhược điểm lớn từ quan điểm hiện tại của tôi. Lưu trữ một tài liệu bận rộn (nhiều thay đổi thông qua nhiều người dùng được mong đợi) như là một thực thể signle sẽ gây ra xung đột xảy ra. Nếu người dùng A lưu trữ các thay đổi của anh ta/cô ấy đối với tài liệu, người dùng B sẽ nhận được lỗi xung đột khi anh/cô ấy hoàn tất việc nhập cập nhật của anh ấy/cô ấy. Tôi có thể tưởng tượng có thể sửa lỗi này mà không có kiến ​​thức của người dùng thông qua việc tải xuống lại tài liệu trước khi thử lại.

Multi User Update problem

Nhưng nếu tài liệu là khá lớn thì sao? Tôi sẽ loại trừ chúng để trở nên khá nổi lên theo thời gian mà sẽ gây ra một số chậm trễ đáng chú ý trong quá trình lưu, đặc biệt nếu quá trình thử lại phải xảy ra nhiều lần do nhiều người dùng cập nhật tài liệu cùng một lúc.

Một vấn đề khác mà tôi thấy là chỉnh sửa. Mọi người dùng đều được phép chỉnh sửa đóng góp của mình. Bây giờ, nếu chúng được lưu trữ trong một tài liệu có thể khó viết một trình xử lý auth solid.

Ok, bây giờ hãy xem xét cách tiếp cận nhiều tài liệu. Câu hỏi, câu trả lời và nhận xét sẽ được lưu trữ trong tài liệu của riêng họ. Ưu điểm: chỉ chủ sở hữu thực sự của tài liệu mới có thể gây xung đột, điều gì đó sẽ không xảy ra quá thường xuyên. Là những yếu tố khá nhỏ của toàn bộ, việc tải xuống lại sẽ không tốn nhiều thời gian. Hơn nữa thói quen auth nên khá dễ nhận ra.

Bây giờ, đây là nhược điểm. Các tài liệu duy nhất là thực sự dễ dàng để truy vấn và hiển thị. Có rất nhiều đoạn trích không được sắp xếp nằm xung quanh dường như là một điều lộn xộn vì tôi không thực sự có được cái nhìn thực tế để trình bày tôi với 100% sẵn sàng sử dụng đối tượng JSON chứa toàn bộ mục theo định dạng có trật tự và có cấu trúc.

enter image description here

Tôi hy vọng tôi đã có thể giao tiếp vấn đề thực tế. Tôi cố gắng quyết định giải pháp nào phù hợp hơn với tôi, những vấn đề nào dễ khắc phục hơn. Tôi tưởng tượng giải pháp đầu tiên là giải pháp đẹp nhất về lưu trữ và truy vấn, nhưng giải pháp thứ hai là giải pháp thực tế hơn có thể giải quyết thông qua quản lý khóa tốt hơn trong chế độ xem (tôi chưa hoàn toàn vào nguyên tắc khóa).

Cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn trước :)

Trả lời

8

Đi với tùy chọn thứ hai của bạn. Nó dễ dàng hơn nhiều so với việc phải đối phó với những xung đột. Dưới đây là một số ví dụ tài liệu làm thế nào tôi có thể cấu trúc dữ liệu:

{ 
    _id: 12345, 
    type: 'question', 
    slug: 'couchdb-single-document-vs-joining-documents-together', 
    markdown: 'Im tryting to decide the best approach for a CouchApp (no middleware). Since there are similarities to...' , 
    user: 'roman-geber', 
    date: 1322150148041, 
    'jquery.couch.attachPrevRev' : true 
} 
{ 
    _id: 23456, 
    type: 'answer' 
    question: 12345, 
    markdown: 'Go with your second option...', 
    user : 'ryan-ramage', 
    votes: 100, 
    date: 1322151148041, 
    'jquery.couch.attachPrevRev' : true 
} 
{ 
    _id: 45678, 
    type: 'comment' 
    question: 12345, 
    answer: 23456, 
    markdown : 'I really like what you have said, but...' , 
    user: 'somedude', 
    date: 1322151158041, 
    'jquery.couch.attachPrevRev' : true 
} 

Để lưu trữ các phiên bản của mỗi người, tôi sẽ lưu trữ các phiên bản cũ như file đính kèm trên doc đang được chỉnh sửa. Nếu bạn sử dụng trình khách jquery cho couchdb, bạn sẽ nhận được nó miễn phí bằng cách thêm jquery.couch.attachPrevRev = true.Xem Versioning docs in CouchDB by jchris

Tạo một cái nhìn như thế này

fullQuestion : { 
    map : function(doc) { 
     if (doc.type == 'question') emit([doc._id, null, null], null); 
     if (doc.type == 'answer') emit([doc.question, doc._id, null], null); 
     if (doc.type == 'comment') emit([doc.question, doc.answer, doc._id], null) ; 
    } 
} 

Và truy vấn xem như thế này

http://localhost:5984/so/_design/app/_view/fullQuestion?startkey=['12345']&endkey=['12345',{},{}]&include_docs=true 

(Lưu ý: Tôi đã không URL mã hóa truy vấn này, nhưng nó là dễ đọc hơn)

Điều này sẽ giúp bạn có được tất cả các tài liệu liên quan cho câu hỏi mà bạn sẽ cần để xây dựng trang. Điều duy nhất là chúng sẽ không được sắp xếp theo ngày tháng. Bạn có thể sắp xếp chúng ở phía máy khách (trong javascript).

EDIT: Đây là một lựa chọn thay thế cho xem và truy vấn

Dựa trên tên miền của bạn, bạn có biết một số sự kiện. Bạn biết một câu trả lời không thể tồn tại trước khi một câu hỏi tồn tại, và một bình luận về một câu trả lời không thể tồn tại trước khi câu trả lời tồn tại. Vì vậy, hãy tạo ra một quan điểm cho rằng có thể làm cho nó nhanh hơn để tạo ra các trang hiển thị, tôn trọng trật tự của sự vật:

fullQuestion : { 
    map : function(doc) { 
     if (doc.type == 'question') emit([doc._id, doc.date], null); 
     if (doc.type == 'answer') emit([doc.question, doc.date], null); 
     if (doc.type == 'comment') emit([doc.question, doc.date], null); 
    } 
} 

này sẽ giữ tất cả các tài liệu có liên quan với nhau, và giữ cho chúng được sắp xếp theo ngày. Đây là truy vấn mẫu

http://localhost:5984/so/_design/app/_view/fullQuestion?startkey=['12345']&endkey=['12345',{}]&include_docs=true 

Điều này sẽ lấy lại tất cả tài liệu bạn cần, được đặt hàng từ cũ nhất đến mới nhất. Bây giờ bạn có thể nén qua các kết quả, biết rằng các đối tượng gốc sẽ ở trước các kết quả con, như sau:

function addAnswer(doc) { 
    $('.answers').append(answerTemplate(doc)); 
} 

function addCommentToAnswer(doc) { 
    $('#' + doc.answer).append(commentTemplate(doc)); 
} 

$.each(results.rows, function(i, row) { 
    if (row.doc.type == 'question') displyQuestionInfo(row.doc); 
    if (row.doc.type == 'answer') addAnswer(row.doc); 
    if (row.doc.type == 'comment') addCommentToAnswer(row.doc) 
}) 

Vì vậy, bạn không phải thực hiện bất kỳ phân loại phía khách hàng nào.

Hy vọng điều này sẽ hữu ích.

+0

Hi Ryan! Cảm ơn rất nhiều vì câu trả lời chi tiết và dễ hiểu của bạn. Bạn đã nói với tôi một số điều tôi chưa biết. Tôi đã quản lý để thực hiện một phiên bản đầu tiên của tùy chọn thứ hai khá nhanh chóng, nhưng sẽ tinh chỉnh nó dựa trên đầu vào của bạn. Cảm ơn rất nhiều! :) –

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