¿Cómo haría una asociación de muchos a muchos con MongoDB?
Por ejemplo; supongamos que tiene una tabla de usuarios y una tabla de roles. Los usuarios tienen muchos roles y los roles tienen muchos usuarios. En tierra SQL, crearía una tabla UserRoles.
Users:
Id
Name
Roles:
Id
Name
UserRoles:
UserId
RoleId
¿Cómo se maneja el mismo tipo de relación en MongoDB?
many-to-many
associations
mongodb
Josh Close
fuente
fuente
Respuestas:
Dependiendo de sus necesidades de consulta, puede poner todo en el documento del usuario:
Para obtener todos los ingenieros, use:
Si desea mantener los roles en documentos separados, puede incluir el _id del documento en la matriz de roles en lugar del nombre:
y configurar los roles como:
fuente
En lugar de tratar de modelar de acuerdo con nuestros años de experiencia con RDBMS, he encontrado que es mucho más fácil modelar soluciones de repositorio de documentos utilizando MongoDB, Redis y otros almacenes de datos NoSQL optimizando los casos de uso de lectura, al tiempo que considero el atómico operaciones de escritura que deben ser compatibles con los casos de uso de escritura.
Por ejemplo, los usos de un dominio "Usuarios en roles" son los siguientes:
Esto se puede modelar como las siguientes plantillas de documentos:
Para admitir los usos de alta frecuencia, como las funciones relacionadas con el rol de la entidad Usuario, User.Roles se desnormaliza intencionalmente, se almacena en el Usuario, así como Role.Users que tienen almacenamiento duplicado.
Si no es evidente en el texto, pero este es el tipo de pensamiento que se fomenta cuando se utilizan repositorios de documentos.
Espero que esto ayude a cerrar la brecha con respecto al lado de lectura de las operaciones.
Para el lado de la escritura, lo que se recomienda es modelar según las escrituras atómicas. Por ejemplo, si las estructuras de documentos requieren adquirir un bloqueo, actualizar un documento, luego otro y posiblemente más documentos, luego liberar el bloqueo, es probable que el modelo haya fallado. El hecho de que podamos construir bloqueos distribuidos no significa que se supone que debemos usarlos.
Para el caso del modelo Usuario en roles, las operaciones que amplían nuestra capacidad de evitar bloqueos de escritura atómica es agregar o eliminar un Usuario de un Rol. En cualquier caso, una operación exitosa resulta en la actualización de un solo Usuario y un solo documento de Rol. Si algo falla, es fácil realizar la limpieza. Esta es la única razón por la que el patrón de la Unidad de trabajo surge bastante cuando se utilizan repositorios de documentos.
La operación que realmente estira nuestra evitación de bloqueos de escritura atómica es borrar un Rol, lo que daría como resultado muchas actualizaciones de Usuario para eliminar el Role.name de la matriz User.roles. Esta operación de clear entonces generalmente se desaconseja, pero si es necesario se puede implementar ordenando las operaciones:
En el caso de un problema, que es más probable que ocurra dentro del paso 2, una reversión es fácil ya que el mismo conjunto de nombres de usuario del paso 1 se puede usar para recuperar o continuar.
fuente
Acabo de encontrarme con esta pregunta y, aunque es antigua, pensé que sería útil agregar un par de posibilidades que no se mencionan en las respuestas dadas. Además, las cosas se han movido un poco en los últimos años, por lo que vale la pena enfatizar que SQL y NoSQL se están acercando entre sí.
Uno de los comentaristas planteó la sabia actitud de precaución de que "si los datos son relacionales, use relacionales". Sin embargo, ese comentario solo tiene sentido en el mundo relacional, donde los esquemas siempre vienen antes de la aplicación.
MUNDO RELACIONAL: Datos de estructura> Escribir aplicación para obtenerlo
MUNDO NOSQL: Aplicación de diseño> Estructurar datos en consecuencia
Incluso si los datos son relacionales, NoSQL sigue siendo una opción. Por ejemplo, las relaciones uno a muchos no son ningún problema y están ampliamente cubiertas en los documentos de MongoDB
UNA SOLUCIÓN DE 2015 A UN PROBLEMA DE 2010
Desde que se publicó esta pregunta, ha habido intentos serios de acercar noSQL a SQL. El equipo dirigido por Yannis Papakonstantinou de la Universidad de California (San Diego) ha estado trabajando en FORWARD , una implementación de SQL ++ que pronto podría ser la solución a problemas persistentes como el publicado aquí.
En un nivel más práctico, el lanzamiento de Couchbase 4.0 ha significado que, por primera vez, puedes hacer uniones nativas en NoSQL. Usan su propio N1QL. Este es un ejemplo de un
JOIN
de sus tutoriales :N1QL permite la mayoría de las operaciones SQL, si no todas, incluidas la agregación, el filtrado, etc.
LA SOLUCIÓN HÍBRIDA NO TAN NUEVA
Si MongoDB sigue siendo la única opción, me gustaría volver a mi punto de que la aplicación debe tener prioridad sobre la estructura de los datos. Ninguna de las respuestas menciona la incrustación híbrida, por lo que la mayoría de los datos consultados se incrustan en el documento / objeto, y las referencias se guardan para una minoría de los casos.
Ejemplo: ¿puede esperar información (que no sea el nombre del rol)? ¿Podría el arranque de la aplicación ser más rápido al no solicitar nada que el usuario aún no necesita?
Este podría ser el caso si el usuario inicia sesión y necesita ver todas las opciones para todos los roles a los que pertenece. Sin embargo, el usuario es un "ingeniero" y las opciones para este rol rara vez se usan. Esto significa que la aplicación solo necesita mostrar las opciones para un ingeniero en caso de que quiera hacer clic en ellas.
Esto se puede lograr con un documento que le dice a la aplicación al inicio (1) a qué roles pertenece el usuario y (2) dónde obtener información sobre un evento vinculado a un rol en particular.
O, mejor aún, indexe el campo role.name en la colección de roles, y es posible que tampoco necesite incrustar ObjectID ().
Otro ejemplo: ¿hay información sobre TODOS los roles solicitados TODO el tiempo?
También podría ser el caso de que el usuario inicie sesión en el tablero y el 90% del tiempo realiza tareas vinculadas a la función de "ingeniero". La incrustación híbrida se puede hacer para ese rol en particular en su totalidad y mantener referencias para el resto únicamente.
No tener esquemas no es solo una característica de NoSQL, podría ser una ventaja en este caso. Es perfectamente válido anidar diferentes tipos de objetos en la propiedad "Roles" de un objeto de usuario.
fuente
en caso de que el empleado y la empresa sean objeto de entidad, intente utilizar el siguiente esquema:
fuente