Node and Sequelize problem - creating associated entities

Hi All - stuck on something I can’t seem to get unblocked on. I have a Stack Overflow question detailing it, and include the fill text here. Feel free to answer here or there (or both!) since if you can get me unstuck you deserve clout on any and every platform!


Link: https://stackoverflow.com/questions/63216558/how-to-create-associative-entities-with-sequelize?noredirect=1#comment111799544_63216558


Original post:

I have two tables and a third associative entity table, such as this:

ERD showing Books and Languages, both with one-to-many relationship to BookLanguages

Books:

module.exports = (sequelize, DataTypes) => {
  const Book = sequelize.define(
    "Book",
    {
      title: DataTypes.STRING,
      author: DataTypes.STRING,
    },
    {}
  );
    
  Book.associate = function (models) {

    Book.belongsToMany(models.Language, {
      as: "BookLanguages",
      through: "BookLanguages",
      foreignKey: "bookId",
    });
  };
      
  return Book;
};

Languages:

module.exports = (sequelize, DataTypes) => {
  const Language = sequelize.define(
    "Language",
    {
      language: DataTypes.STRING,
    },
    {}
  );

  Language.associate = function (models) {

    Language.hasMany(models.Book, {
      as: "BookLanguages",
      through: "BookLanguages",
      foreignKey: "languageId",
    });
  };
  
  return Language;
};

Languages contains these records: 1. English, 2. French

I want to create a new book that is available in English and French.

Books Controller:

const Sequelize = require("sequelize");
const db = require("../../models/index");
const Book = db.Book;
const Language = db.Language;

exports.createBook = (req, res) => {
  Book.create({
   title: req.body.title,
   author: req.body.author,
   BookLanguages: req.body.languages // an array [1, 2]
 }, {
   include: [ { association: Language, as: "BookLanguages" } ]
  })
    .then((book) => {
      res.json({ status: 200, message: "Book created successfully!" });
    })
    .catch((err) => {
      res.json({ status: 400, message: err });
    });
};

AFAICT from the Sequelize docs, this should be sufficient, but I am getting an error:

TypeError: Cannot read property 'language' of undefined

Can anyone see what I’m missing, or what I may have misunderstood about setting up these associations / associative entities?


Follow up comment from me: “The Sequelize docs include this line: “An instance can be created with nested association in one step, provided all elements are new.” I suspect the problem is that the languages elements are not being newly created - I’m trying to link elements that have already been created to a new one (Existing languages associated with a new book).”

Normally you need associative table only for “many-to-many” relationships, I frankly don’t see it here… In my opinion one title in English and French has to have 2 different ids, meaning you will have “one-to-one” relationship in between books and languages

It’s a simplified and contrived example.

The contents of the tables isn’t important - the desire to link them via an associative table, and how to do that upon creation is the point of the question.