Diseño de esquema mongodb para blogs

¿Cómo diseñaría el esquema para un sitio tipo blog con bases de datos basadas en documentos (mongodb)? El sitio tiene los siguientes objetos: Usuario, Artículo, Comentario. El usuario puede agregar comentarios al artículo. Cada usuario también puede votar exactamente una vez por comentario.

Quiero poder hacer estas consultas de manera eficiente:
1. obtener el artículo A, comentarios sobre el artículo A y número de votos por comentarios
2. obtenga todos los comentarios del usuario B en todos los artículos
3. obtener todos los comentarios que el usuario B votó

Mi primer bash es colocar artículos y comentarios en colecciones separadas y los comentarios pueden contener una lista de usuarios que votaron por él. Esto hace que las consultas 1 y 2 sean simples. Y para 3, agregué la colección de Votos, que mantiene un seguimiento de los votos de los usuarios.

Hay una desventaja obvia, como la duplicación de los datos de voto de los usuarios y la consulta 1 tomará dos llamadas a la base de datos. ¿Hay un mejor enfoque?

Article { "user_id" } Comment { "user_id", "article_id", [user_voted], } Vote { "user_id", "comment_id", } 

 Article { "_id" : "A", "title" : "Hello World", "user_id" : 12345, "text" : 'My test article', "comments" : [ { 'text' : 'blah', 'user_id' : 654321, 'votes' : [987654]}, { 'text' : 'foo', 'user_id' : 987654, 'votes' : [12345, 654321] }, ... ] } 

La premisa básica aquí es que he nested los Comments dentro del Article . Los Votes solo se aplican a un Comment , por lo que se han almacenado como una matriz con cada Comment . En este caso, acabo de almacenar el user_id. Si desea almacenar más información (time_created, etc.), puede votar una matriz de objetos:

 ... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ... 

Cómo realizar sus consultas de manera eficiente:

  1. obtener el artículo A, comentarios sobre el artículo A y número de votos por comentario
 db.articles.find( { _id : 'A' } ) 

Esto obtiene todo con una consulta. Es posible que deba hacer alguna lógica del lado del cliente para contar los votos por comentario, pero esto es bastante trivial.

  1. recibe todos los comentarios del usuario B en todos los artículos
 db.articles.ensureIndex( { "comments.user_id" : 1 } ) db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields 

El índice permitirá buscar de manera eficiente los comentarios dentro de un documento.

Actualmente no hay forma de extraer solo las coincidencias de una sub-matriz. Esta consulta devolverá todos los artículos con comentarios de ese usuario. Si esto es potencialmente demasiada información, puede hacer algunos ajustes.

 db.articles.find( { "comments.user_id" : 987654 }, { "title" : 1, "comments.user_id" : 1 }) 
  1. obtener todos los comentarios El usuario B votó por
 db.articles.ensureIndex( { "comments.votes" : 1 } ) db.articles.find( { "comments.votes" : 987654 } ) 

Una vez más, esto devolverá todos los artículos, no solo los comentarios.

Hay una compensación que se hará aquí. Devolver el artículo puede parecer que estamos devolviendo demasiados datos. Pero, ¿qué planea mostrar al usuario cuando realiza la consulta n. ° 3?

Obtener una lista de “comentarios que he votado” no es muy útil sin el comentario en sí. Por supuesto, el comentario no es muy útil sin el artículo en sí (o al menos solo el título).

La mayoría de las veces, la consulta n. ° 3 se convierte en una unión de Votes a Comments a Articles . Si ese es el caso, entonces ¿por qué no volver a traer los artículos para empezar?

    Intereting Posts