2011-11-24 15 views
7

Sto provando a decidere l'approccio migliore per una CouchApp (senza middleware). Dato che ci sono delle somiglianze con la mia idea, supponiamo di avere una pagina StackOverflow memorizzata in un CouchDB. In sostanza consiste nella domanda reale in alto, risposte e comandi. Questi sono fondamentalmente tre strati.CouchDB: documento singolo contro "unire" i documenti insieme

Esistono due modi per memorizzarlo. Sia all'interno di un singolo documento che contiene una rappresentazione JSON adatta dei dati, o memorizzare ogni parte della voce all'interno di un documento separato combinandoli successivamente attraverso una vista (simile a questo: http://www.cmlenz.net/archives/2007/10/couchdb-joins)

Ora, entrambi gli approcci possono andare bene, eppure entrambi hanno enormi aspetti negativi dal mio attuale punto di vista. Memorizzare un documento occupato (sono previste molte modifiche attraverso più utenti) in quanto un'entità signolo potrebbe causare conflitti. Se l'utente A memorizza le sue modifiche al documento, l'utente B riceve un errore di conflitto una volta che ha finito di digitare il suo/l'aggiornamento. Posso immaginare che sia possibile risolvere questo problema senza la conoscenza degli utenti attraverso il nuovo download del documento prima di riprovare.

Multi User Update problem

Ma cosa succede se il documento è piuttosto grande? Farò in modo che non vengano saltati nel tempo, il che metterebbe un notevole ritardo in un processo di salvataggio, specialmente se il processo di ripetizione deve avvenire più volte a causa del numero elevato di utenti che aggiornano un documento contemporaneamente.

Un altro problema che vedrei è la modifica. Ogni utente dovrebbe essere autorizzato a modificare i suoi contributi. Ora, se sono memorizzati in un documento, potrebbe essere difficile scrivere un gestore di autenticazione solido.

Ok, ora vediamo l'approccio con più documenti. Domanda, risposte e commenti verrebbero archiviati all'interno dei propri documenti. Vantaggio: solo il proprietario effettivo del documento può causare conflitti, cosa che non accadrà troppo spesso. Essendo elementi piuttosto piccoli del tutto, il ridownloading non richiederebbe molto tempo. Inoltre la routine auth dovrebbe essere abbastanza facile da realizzare.

Ora ecco il rovescio della medaglia. Il singolo documento è davvero facile da interrogare e visualizzare. Avere un sacco di frammenti non ordinati in giro sembra una cosa disordinata dato che non ho avuto la possibilità di presentarmi con un oggetto JSON 100% pronto per l'uso contenente l'intero articolo in un formato ordinato e strutturato.

enter image description here

spero sono stato in grado di comunicare il problema reale. Cerco di decidere quale soluzione sarebbe più adatta a me, quali problemi più facili da superare. Immagino che la prima soluzione sia la più bella in termini di archiviazione e interrogazione, ma la seconda è la più pratica risolvibile attraverso una migliore gestione delle chiavi all'interno della vista (non sono ancora del tutto nel principio delle chiavi).

La ringrazio molto per il vostro aiuto in anticipo :)

risposta

8

Vai con il seconda opzione. È molto più facile che dover affrontare i conflitti. Ecco alcuni esempi di documenti come avrei potuto strutturare i dati:

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

Per memorizzare le revisioni di ciascuno, vorrei conservare le vecchie versioni come allegati sul documento in fase di modifica. Se usi il client jquery per couchdb, lo ottieni gratuitamente aggiungendo jquery.couch.attachPrevRev = true.Vedi Versioning docs in CouchDB by jchris

creare una vista come questo

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

e Query la vista in questo modo

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

(Nota: io non ho URL codificato questa query, ma è più leggibile)

Questo ti porterà tutti i documenti relativi alla domanda che ti servirà per costruire la pagina. L'unica cosa è che non saranno ordinati per data. Puoi ordinarli sul lato client (in javascript).

EDIT: Qui è un'opzione alternativa per la vista e interrogazione

Sulla base di dominio, lo sai alcuni fatti. Sai che una risposta non può esistere prima che una domanda esistesse, e un commento su una risposta non può esistere prima che esistesse una risposta. Quindi, consente di effettuare una vista che potrebbe renderlo più veloce per creare la pagina di visualizzazione, rispettando l'ordine delle cose:

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

Ciò manterrà tutti i relativi documenti insieme, e tenerli ordinati per data. Ecco una query di esempio

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

Questa operazione consente di recuperare tutti i documenti necessari, ordinati dal più vecchio al più recente. È ora possibile zip attraverso i risultati, sapendo che gli oggetti padre saranno prima di quelle dei bambini, in questo modo:

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

Allora non dovete eseguire qualsiasi ordinamento lato client.

Spero che questo aiuti.

+0

Ciao Ryan! Grazie mille per la tua risposta dettagliata e comprensibile. Mi hai detto alcune cose che non sapevo ancora. Sono riuscito a implementare una prima versione della seconda opzione piuttosto rapidamente, ma la ottimizzerò in base al tuo input. Molte grazie! :) –

Problemi correlati