mongodb - query - nosql tutorial
Modelando relaciones de amistad de amigo en MongoDB (3)
Esto parece una gran cantidad de ida y vuelta, en comparación con lo que podríamos hacer con una unión en una base de datos relacional.
Todo esto es muy relativo. Tu suposición básica sobre la obtención de "amigos de amigos de amigos" es correcta, son algunos saltos y un par de "distinciones" en la memoria.
Sin embargo, desde la perspectiva en bruto del "trabajo total realizado", esto no es muy diferente de lo que tendría que hacer con SQL. Sí, es una consulta SQL relativamente simple, pero el servidor todavía tiene que hacer básicamente la misma cantidad de trabajo, dar o tomar algo de tráfico de red.
¿Existe una manera más eficiente de hacer esto en MongoDB, o es este un problema más adecuado para un RDBMS?
¿Hay una mejor manera en MongoDB? Probablemente no. Sin embargo, hacer "uniones automáticas" en SQL no se puede escalar fácilmente en varios servidores. De hecho, tratar de hacer esto en múltiples servidores básicamente se convierte en un proceso similar al proceso de MongoDB.
Técnicamente, este es un trabajo que se realiza mejor mediante una base de datos gráfica que no es ni MongoDB ni un RDBMS.
Para bases de datos de gráficos, puede echar un vistazo a Trinity para .NET o NEO4J .
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 atascado en la mejor manera de lograrlo en MongoDB. Almacenamos las ID de usuario de los amigos de un usuario en una matriz en el documento del usuario, por lo que la solución obvia es hacer esto:
- Extraiga todas las ID de usuario de amigo del documento de usuario
- Extraiga todas las matrices de amigos de los documentos de usuario de esos amigos (usando $ en la consulta de todas las ID de amigos), combine el lado de la aplicación en un solo conjunto, luego combínelo con las ID de usuarios de primer nivel para obtener un conjunto de todos los amigos y amigos de amigos
- Use ese conjunto para realizar la consulta final (usando $ in) entre 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 una manera más eficiente de hacer esto en MongoDB, o es este un problema más adecuado para un RDBMS?
Creo que esto es algo que se maneja mejor con un RDBMS (a excepción de los DB de gráficos) ya que claramente necesita realizar una operación de "unión". 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 de "unión" de forma atómica puede resultar demasiado costosa si tiene un gran grupo de nodos de base de datos y una gran cantidad de usuarios.
Si no está preocupado por la consistencia 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 de JavaScript que realizará la consulta completa en MongoDB, o use una operación MapReduce para consultas distribuidas más eficientes.
Le hice esta misma pregunta a Eliot Horowitz recientemente en la conferencia de MongoDB SV. Dijo que la forma en que lo estructuraría sería almacenar a los amigos de cada usuario como documentos incrustados dentro de cada usuario. Por ejemplo, la estructura podría verse así:
{
_id : ObjectId("4e77bb3b8a3e000000004f7a"),
username : "alex",
friends : ["283956723823626626aa", "226567377578888888as", "8738783888aas88a8a88" ]
}
entonces puedes 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 Multikeys para obtener más información".
Así que para encontrar a todos los amigos de "alex" puedo hacer:
db.user.find ({''friends'': ''4e77bb3b8a3e000000004f7a''});