2011-11-24 13 views
7

Estoy tratando de decidir el mejor enfoque para un CouchApp (sin middleware). Dado que hay similitudes con mi idea, supongamos que tenemos una página stackoverflow almacenada en un CouchDB. En esencia, consiste en la pregunta real en la parte superior, las respuestas y los commets. Esos son básicamente tres capas.CouchDB: documento único frente a "unión" de documentos juntos

Hay dos maneras de almacenarlo. Ya sea en un solo documento que contenga una representación JSON adecuada de los datos, o almacene cada parte de la entrada en un documento separado combinándolos posteriormente a través de una vista (similar a esto: http://www.cmlenz.net/archives/2007/10/couchdb-joins)

Ahora, ambos enfoques pueden estar bien, sin embargo, ambos tienen desventajas masivas desde mi punto de vista actual. Almacenar un documento ocupado (se esperan muchos cambios a través de múltiples usuarios) ya que una entidad de firma causaría conflictos. Si el usuario A almacena sus cambios en el documento, el usuario B recibiría un error de conflicto una vez que haya terminado de escribir su actualización. Me imagino que es posible arreglar esto sin el conocimiento del usuario a través de una nueva descarga del documento antes de volver a intentarlo.

Multi User Update problem

Pero ¿y si el documento es bastante grande? Excepto que se conviertan en una explosión con el tiempo, lo que retrasaría bastante el proceso de salvar, especialmente si el proceso de reintento tiene que ocurrir varias veces debido a que muchos usuarios actualizan un documento al mismo tiempo.

Otro problema que vería es la edición. Todos los usuarios deberían poder editar sus contribuciones. Ahora, si están almacenados dentro de un documento, puede ser difícil escribir un controlador de autenticación sólido.

Bien, ahora veamos el enfoque de documentos múltiples. Pregunta, Respuestas y Comentarios se almacenarán dentro de sus propios documentos. Ventaja: solo el propietario real del documento puede causar conflictos, algo que no ocurrirá con demasiada frecuencia. Al ser elementos más bien pequeños del todo, volver a descargar no tomaría mucho tiempo. Además, la rutina de autenticación debería ser bastante fácil de realizar.

Ahora esta es la desventaja. El documento individual es muy fácil de consultar y mostrar. Tener muchos fragmentos sin clasificar por ahí parece algo desordenado ya que realmente no tuve la visión real de presentarme un objeto JSON 100% listo para usar que contiene el ítem completo en un formato ordenado y estructurado.

enter image description here

espero que he sido capaz de comunicar el problema real. Intento decidir qué solución sería más adecuada para mí, qué problemas son más fáciles de superar. Imagino que la primera solución es la más bonita en términos de almacenamiento y consultas, pero la segunda más práctica se puede resolver a través de una mejor administración de claves dentro de la vista (todavía no estoy del todo en el principio de las claves).

Muchas gracias por su ayuda de antemano :)

Respuesta

8

ir con su segunda opción. Es mucho más fácil que tener que lidiar con los conflictos. Aquí hay algunos documentos de ejemplo cómo podría estructurar los datos:

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

Para almacenar las revisiones de cada uno, me gustaría almacenar las versiones antiguas como archivos adjuntos en el documento que se está editando. Si usa el cliente jquery para couchdb, lo obtiene de forma gratuita agregando jquery.couch.attachPrevRev = true.Ver Versioning docs in CouchDB by jchris

Crear una vista como esta

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

y consultar la vista como esto

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

(Nota: Yo no he URL codificada esta consulta, pero es más fácil de leer)

Esto le dará todos los documentos relacionados para la pregunta que necesitará para compilar la página. Lo único es que no se ordenarán por fecha. Puede ordenarlos en el lado del cliente (en javascript).

EDITAR: Esta es una opción alternativa para la vista y consulta

Sobre la base de su dominio, usted sabe algunos hechos. Usted sabe que una respuesta no puede existir antes de que existiera una pregunta, y un comentario sobre una respuesta no puede existir antes de que existiera una respuesta. Así que vamos a hacer una vista que podría hacerlo más rápido para crear la página de visualización, respetando el orden de las cosas:

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

Esto mantendrá todos los documentos relacionados entre sí, y mantenerlos por fecha. Aquí hay una consulta de ejemplo

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

Esto le devolverá todos los documentos que necesite, ordenados de la más vieja a la más reciente. Ahora puede comprimir a través de los resultados, a sabiendas de que los padres se opongan serán antes que los niños, como este:

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

Así que usted no tiene que realizar ninguna clasificación lado del cliente.

Espero que esto ayude.

+0

¡Hola Ryan! Muchas gracias por su respuesta detallada y comprensible. Me dijiste algunas cosas que aún no sabía. Me las he arreglado para implementar una primera versión de la segunda opción bastante rápido, pero la ajustaré según su entrada. ¡Muchas gracias! :) –

Cuestiones relacionadas