2010-05-15 7 views
17

Estoy trabajando en una aplicación de prueba de concepto para una red social estilo twitter con aproximadamente 500k usuarios. No estoy seguro de cuál es la mejor manera de diseñar el 'esquema'diseño 'esquema' para una red social

¿debo incrustar las suscripciones de un usuario o tener una colección de 'suscripciones' separada y usar referencias de db? Si incrustar, todavía tengo que realizar una consulta para obtener todos los seguidores de un usuario. p.ej.

Dado el siguiente usuario:

{ 
"username" : "alan", 
"photo": "123.jpg", 
"subscriptions" : [ 
    {"username" : "john", "status" : "accepted"}, 
    {"username" : "paul", "status" : "pending"} 
    ] 
} 

para encontrar todos los suscriptores de Alan, que tendría que ejecutar algo como esto:

db.users.find({'subscriptions.username' : 'alan'}); 

desde el punto de vista del rendimiento, es que cualquier peor o mejor que tener una colección de suscripciones por separado?

Además, al mostrar una lista de suscripciones/suscriptores, actualmente tengo problemas con n + 1 porque el documento de suscripción me dice el nombre de usuario pero no otros atributos que pueda necesitar, como la foto de perfil. ¿Hay alguna práctica recomendada para tales situaciones?

gracias Alan

Respuesta

11

primer lugar, usted debe saber las ventajas y desventajas que se van a obtener con MongoDB y cualquier otra base de datos NoSQL (pero se dan cuenta de que soy un fan de ella). Si intenta normalizar sus datos por completo, está cometiendo un gran error. Incluso en las bases de datos relacionales, cuanto más grande es la aplicación, más se desnormalizan sus datos (consulte this post en Hot Potato). He visto esto una y otra vez. No deberías volverte loco y hacer un gran desastre, pero no te preocupes por repetir la información en dos lugares. Uno de los puntos principales (en mi opinión) de NoSQL es que su esquema se traslada a su código y no solo a la base de datos.

Ahora, para responder a su pregunta, creo que su estrategia inicial es lo que haría. MongoDB puede colocar índices en elementos que son matrices, por lo que hará que las cosas sean mucho más rápidas si está buscando cuántas amistades tiene un usuario. Pero en realidad, la única manera de estar realmente seguro es ejecutar algún tipo de programa de prueba que genere una base de datos llena de nombres y relaciones.

Puede escribir una entrada en Python o Perl o lo que quiera, y usar un archivo de nombres para generar algunas relaciones. Consulte Census website, que tiene una lista de apellidos. Descargar el archivo dist.all.last y escribir algún programa como:

#! /usr/bin/env python 
import random as rand 

f = open('dist.all.last') 
names = [] 
for line in f: 
    names.append(line.split()[0]) 

rels = {} 
for name in names: 
    numOfFriends = rand.randint(0, 1000) 
    rels[name] = [] 
    for i in range(numOfFriends): 
    newFriend = rand.choice(names) 
    if newFriend != name: #cannot be friends with yourself 
     rels[name].append(newFriend) 

# take relationships (i.e. rels) and write them to MongoDB 

Además, como nota general, su nombres de campos parecen tipo de largo. Recuerde que los nombres de campo se repiten con en cada documento en esa colección porque no puede confiar en que un campo esté en cualquier otro documento. Para ahorrar espacio, una estrategia general es usar nombres de campo más cortos como "unam" en lugar de "nombre de usuario", pero eso es algo pequeño. Ver el gran consejo en thesetwo publicaciones.

EDIT:

En realidad, en ponderar su problema un poco más, me gustaría hacer una sugerencia más: romper los tipos de suscripción en diferentes campos para hacer los índices más eficiente.Por ejemplo, en lugar de:

{ 
"username" : "alan", 
"photo": "123.jpg", 
"subscriptions" : [ 
    {"username" : "john", "status" : "accepted"}, 
    {"username" : "paul", "status" : "pending"} 
    ] 
} 

Como se ha dicho anteriormente, me gustaría hacer esto:

{ 
"username" : "alan", 
"photo": "123.jpg", 
"acc_subs" : [ "john" ], 
"pnd_subs" : [ "paul" ] 
} 

Así que usted podría tener un índice para cada tipo de suscripción, con lo que consultas como "Hoy muchos ¿La gente tiene a Paul como pendiente? y "¿Cuántas personas se suscriben a Pablo?" súper rápido de cualquier manera. La indexación de Mongo sobre valores ordenados es realmente una victoria épica.

+2

buena publicación, +1, pero no estoy de acuerdo en hacer nombres cortos. Hazlos el tiempo que sea necesario para no tener que explicar nada a otro desarrollador. Luego perfila/optimiza según sea necesario. Si los nombres son un problema de tamaño significativo a medida que escala, entonces refactorice. – Lee

2

@Alan B: Creo que usted es totalmente conseguir MongoDB. Estoy de acuerdo con @daveslab versión de los datos, pero es probable que también desee agregar "seguidores".

{ 
"username" : "alan", 
"photo": "123.jpg", 
"acc_subs" : [ "john" ], 
"pnd_subs" : [ "paul" ] 
"acc_fol" : [ "mike", "ray" ], 
"pnd_fol" : [ "judy" ] 
} 

Sí, hay información duplicada. Depende de la "capa de negocios" garantizar que esta información se actualice correctamente en ambos lugares. Lamentablemente, no hay transacciones en Mongo, afortunadamente, tiene la operación $ addToSet, por lo que está bastante seguro.

Cuestiones relacionadas