CouchDB: Single document vs “joining” documents together

浪尽此生 提交于 2019-12-03 08:10:42
Ryan Ramage

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!