CouchDB: Single document vs “joining” documents together

后端 未结 1 1460
不知归路
不知归路 2021-02-09 06:42

I\'m tryting to decide the best approach for a CouchApp (no middleware). Since there are similarities to my idea, lets assume we have a stackoverflow page stored in a CouchDB. I

1条回答
  •  梦如初夏
    2021-02-09 07:14

    Go with your second option. It's much easier than having to deal with the conflicts. Here are some example docs how I might structure the data:

    {
       _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
    }
    

    To store revisions of each one, I would store the old versions as attachments on the doc being edited. If you use the jquery client for couchdb, you get it for free by adding the jquery.couch.attachPrevRev = true. See Versioning docs in CouchDB by jchris

    Create a view like this

    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) ;
       }
    }
    

    And query the view like this

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

    (Note: I have not url encoded this query, but it is more readable)

    This will get you all of the related documents for the question that you will need to build the page. The only thing is that they will not be sorted by date. You can sort them on the client side (in javascript).

    EDIT: Here is an alternative option for the view and query

    Based on your domain, you know some facts. You know an answer cant exist before a question existed, and a comment on an answer cant exist before an answer existed. So lets make a view that might make it faster to create the display page, respecting the order of things:

    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);
       }
     }
    

    This will keep all the related docs together, and keep them ordered by date. Here is a sample query

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

    This will get back all the docs you will need, ordered from oldest to newest. You can now zip through the results, knowing that the parent objects will be before the child ones, like this:

    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)
    })
    

    So then you dont have to perform any client side sorting.

    Hope this helps.

    0 讨论(0)
提交回复
热议问题