2011-03-07 26 views
26

¿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.mongodb diseño de esquema para blogs

Quiero ser capaz de hacer estas preguntas de manera eficiente:
1. Un artículo get, comentarios sobre el artículo A y # de votos por los comentarios
2. obtener todos los comentarios de usuario B a través de todos los artículos
3. obtener todos los comentarios El usuario B votó por

Mi primer intento es poner 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 duplicar 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", 
} 

Respuesta

28
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 anidado el Comments interior de la Article. El Votes solo se aplica a un Comment, por lo que se almacenaron 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.), entonces se puede vota 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 los comentarios
db.articles.find({ _id : 'A' }) 

Esto consigue 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. obtener todos los comentarios de usuario B a través de 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 del 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 sólo los comentarios.

Aquí hay una solución de compromiso. Devolver el artículo puede parecer que estamos devolviendo demasiados datos. Pero, ¿qué planea mostrar al usuario cuando realiza la consulta n. ° 3?

Obteniendo una lista de "comentarios que he votado" no es terriblemente ú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 transfiere a una combinación de Votes a Comments a Articles. Si ese es el caso, entonces ¿por qué no volver a traer los artículos para empezar?

+3

¿Qué pasa con la limitación de 16MB/documento? –

+0

Si le preocupa que una sola publicación de blog exceda los 16MB (_eso es mucho texto_), entonces deberá hacer un diseño de esquema diferente. Muchos blogs en realidad fuente esto como consultas separadas y por lo que en realidad no acceden a ambas piezas a la vez. Si estas son tus preocupaciones, eliges un esquema diferente. –

+0

Necesito un diseño similar para un blog, necesito buscar los comentarios ordenados por fecha de todos los artículos para moderación. Ahora este resultado también debe ser paginado. ¿Debería seguir apegado a esta arquitectura o llevar la sección de comentarios a otra colección? –

Cuestiones relacionadas