2011-09-12 9 views
17

Necesitamos poder realizar rápidamente consultas en el conjunto de amigos de un usuario y amigos de amigos. Esto sería relativamente sencillo en una base de datos relacional, pero estoy algo atrapado en la mejor manera de lograrlo en MongoDB. Almacenamos las identificaciones de usuario de los amigos de un usuario en una matriz en el documento de usuario, por lo que la solución obvia es hacer esto:Modelando relaciones de amigo de amigo en MongoDB

  • Tire todos los ID de amigo usuario de usuario doc
  • Tire todas las matrices de amistad de documentos de usuarios de esos amigos (usando una consulta de $ en todos los ID de amigo), combine el lado de la aplicación en un conjunto y luego combine eso con los ID de usuario amigos de primer nivel para obtener un conjunto de amigos y amigos
  • Use ese conjunto para realizar la consulta final (usando $ in) en todos los amigos y amigos de amigos

Si bien es sencillo, esto parece una gran cantidad de ida y vuelta, en comparación con lo que podríamos hacer con una combinación en una base de datos relacional. ¿Existe alguna forma más eficiente de hacer esto en MongoDB, o es este un problema más adecuado para un RDBMS?

Respuesta

7

esto parece una enorme cantidad de ida y vuelta, en comparación con lo que podríamos hacer con una combinación en una base de datos relacional

Todo esto es muy relativo. Su suposición básica de obtener "amigos de amigos de amigos" es correcta, son unos pocos saltos y un par de "distincts" en la memoria.

Sin embargo, desde la perspectiva cruda del "trabajo total realizado", esto no es muy diferente de lo que usted haría con SQL. Sí, es una consulta SQL relativamente simple, pero el servidor en sí todavía tiene que hacer básicamente la misma cantidad de trabajo, dar o tomar algo de tráfico de red.

¿Hay una manera más eficiente de hacer esto en MongoDB, o es este un problema más adecuado para un RDBMS?

¿Hay una manera mejor en MongoDB? Probablemente no. Pero hacer "autocombinaciones" en SQL no se escala fácilmente en varios servidores. De hecho, tratar de hacer esto a través de múltiples servidores básicamente se convierte en un proceso similar al proceso MongoDB.

Técnicamente, este es un trabajo mejor realizado por una base de datos de gráficos que no es ni un MongoDB ni un RDBMS.

Para bases de datos de gráficos, puede consultar Trinity for .NET o NEO4J.

2

Creo que esto es algo que se maneja mejor con un RDBMS (salvo DBs de gráfico) ya que claramente necesita realizar una operación "join". Aunque un RDBMS podría implementarlo de la misma manera, podría implementar la unión de manera más eficiente y distribuir la información de manera más eficiente que MongoDB.

Dicho esto, la sobrecarga de realizar la consulta "join" atómicamente podría resultar demasiado costosa si tiene un gran conglomerado de nodos db y una gran cantidad de usuarios.

Si no está preocupado por la coherencia y la atomicidad de la consulta, y todo lo que desea es evitar el intercambio entre la aplicación y la base de datos, puede escribir una función JavaScript que realizará toda la consulta en MongoDB, o use una operación de MapReduce para consultas distribuidas más eficientes.

13

Le pregunté a Eliot Horowitz esta misma pregunta recientemente en la conferencia MongoDB SV. Dijo que la forma en que lo estructuraría es almacenar los amigos de cada usuario como documentos integrados dentro de cada usuario. Por ejemplo, la estructura podría tener este aspecto:

{ 
    _id : ObjectId("4e77bb3b8a3e000000004f7a"), 
    username : "alex", 
    friends : ["283956723823626626aa", "226567377578888888as", "8738783888aas88a8a88" ] 
} 

, entonces puede tener un índice en user.friends

http://www.mongodb.org/display/DOCS/Indexes#Indexes-IndexingArrayElements

"Cuando el valor almacenado de un documento para un campo de clave de índice es una matriz , MongoDB indexa cada elemento de la matriz. Consulte la página de Multikes para más información.

Así que para encontrar todos "Alex" 's amigos que sólo puede hacer:

db.user.find ({ 'amigos': '4e77bb3b8a3e000000004f7a'});

+1

Esto supone que las relaciones de amistad siempre son mutuas ... si alex es amigo de jon, entonces jon también debe ser amigo de alex. – Jay

+0

¿qué tal conseguir amigos en común? –

+0

Mira https://gist.github.com/levicook/4132037 para amigos en común – rodi