Relaciones Muchos a Muchos en SQLite con Tablas Ternarias

Clase 21 de 27Curso de Backend con Node.js: Base de Datos con PostgreSQL

Contenido del curso

Resumen

Cuando una orden de compra necesita contener múltiples productos y, a su vez, un mismo producto puede aparecer en distintas órdenes, estamos frente a una relación muchos a muchos. Resolver este tipo de asociación en Sequelize requiere una tabla intermedia y el uso del método belongs to many. A continuación se explica paso a paso cómo implementar esta estructura de forma práctica.

¿Cómo se resuelve una relación muchos a muchos con una tabla ternaria?

Una tabla ternaria (también llamada tabla de unión o join table) es la pieza clave para conectar dos entidades que se relacionan de forma múltiple. En este caso, se crea una tabla llamada order_product que actúa como puente entre órdenes y productos [01:00].

La estructura de esta tabla contiene:

  • Un ID propio.
  • Un order ID que referencia a la tabla de órdenes.
  • Un product ID que referencia a la tabla de productos.
  • Un campo amount de tipo entero, que representa la cantidad de ese producto dentro de la orden [02:24].

Cada fila de order_product responde tres preguntas: ¿a qué orden pertenece?, ¿qué producto es? y ¿cuántas unidades se pidieron? Es como una línea dentro de una factura.

javascript // Definición simplificada del esquema order_product const OrderProductSchema = { id: { /* ... */ }, orderId: { field: 'order_id', allowNull: false, references: { model: OrderTable, key: 'id' }, }, productId: { field: 'product_id', allowNull: false, references: { model: ProductTable, key: 'id' }, }, amount: { allowNull: false, type: DataTypes.INTEGER, }, };

Es importante que productId no sea único, ya que un mismo producto puede aparecer en múltiples órdenes [02:48].

¿Cómo crear y ejecutar la migración de la tabla intermedia?

Una vez definido el modelo, se genera la migración desde la terminal [03:30]:

bash npm run migrations:generate -- --name order-product

Dentro del archivo generado se importa el esquema de order_product y se aplica con createTable. Un detalle fundamental es respetar la convención de nombres en los archivos: todos los modelos deben terminar con .model en su nombre de archivo para que las importaciones funcionen correctamente [04:00].

Después de configurar la migración, se ejecuta:

bash npm run migrations:run

Esto crea físicamente la tabla de unión entre órdenes y productos en la base de datos [05:08].

¿Cómo se configura belongs to many en Sequelize?

Con la tabla ya creada, el siguiente paso es registrar el modelo en el setup de Sequelize e indicar las asociaciones [05:20]. Aquí es donde entra belongs to many, el método que Sequelize provee para definir relaciones muchos a muchos.

La asociación se define dentro del modelo Order:

javascript // Dentro de Order.associate Order.belongsToMany(Product, { through: OrderProduct, foreignKey: 'order_id', otherKey: 'product_id', });

¿Qué significan los parámetros de esta asociación?

  • through: indica a través de cuál tabla se resuelve la relación, en este caso OrderProduct [06:38].
  • foreignKey: define la llave foránea que corresponde al modelo donde se declara la asociación, aquí order_id [07:08].
  • otherKey: especifica la llave foránea de la otra entidad involucrada, es decir product_id [07:20].

¿Por qué no basta con has many o belongs to?

En una relación uno a muchos se usa has many o belongs to porque existe un vínculo directo entre las tablas. En cambio, la relación muchos a muchos no tiene un vínculo directo entre las dos entidades principales; necesita un intermediario. Por eso Sequelize ofrece belongs to many, que internamente resuelve los joins a través de la tabla ternaria [06:10].

Si estos conceptos de normalización y diseño relacional resultan nuevos, vale la pena estudiar fundamentos de bases de datos relacionales para comprender las reglas de normalización y cómo se diseñan correctamente las relaciones entre tablas [02:58].

Con toda esta configuración lista, el modelo Order ya puede consultar los productos asociados y la cantidad de cada uno. ¿Has implementado relaciones muchos a muchos en tus proyectos? Comparte tu experiencia y las variantes que hayas encontrado.