I am writing a webapp for practice. I have several sequelize models, and querying the db through them so far has been no issue. However, when I tried to use a junction table to return what would be a simple join in SQL, I ran into an issue.
See the query:
Goal: Get every chat a user is a member of.
const models = require('../db/models');
...
...
(inside an api endpoint)
const userChats = await models.User.findOne({
where: { id: req.user.id },
include: [
{
model: models.Chat,
through: models.User_Chat
}
]
});
When I try this, I get the following error:
C:...mypath...node_modulessequelizelibdialectsabstractquery-generator.js:1376
const throughTable = through.model.getTableName();
^
TypeError: Cannot read properties of undefined (reading 'getTableName')
For reference, here are the relevant models and the initialization of those models:
Chat model:
const { sq } = require("../config/db");
const { DataTypes } = require('sequelize');
const Chat = sq.define('Chat', {
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4, // Automatically generate UUID
allowNull: false
},
name: {
type: DataTypes.STRING,
allowNull: false
}
}, {
tableName: 'chats',
timestamps: true,
});
Chat.associate = (models) => {
Chat.belongsToMany(models.User, { through: models.User_Chat, foreignKey: 'chat_id', otherKey: 'user_id' }); //without otherKey, the table had chat_id and UserId, strangely
Chat.hasMany(models.Message, { foreignKey: 'chat_id'});
Chat.belongsTo(models.User, { foreignKey: 'creator_id'});
};
module.exports = { Chat };
User model:
const { sq } = require("../config/db");
const { DataTypes, Sequelize } = require('sequelize');
const User = sq.define("User", {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
validate: {
is: /^[w-]+(?:.[w-]+)*@(?:[w-]+.)+[a-zA-Z]{2,7}$/
},
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
}, {
tableName: 'users'
});
User.associate = (models) => {
User.belongsToMany(models.Chat, { through: models.User_Chat, foreignKey: 'user_id', otherKey: 'chat_id' });
User.hasMany(models.Message, { foreignKey: 'sender_id' });
User.hasMany(models.Chat, { foreignKey: 'creator_id' });
};
module.exports = { User }
User_Chat model:
const { sq } = require("../../config/db");
const { DataTypes, Sequelize } = require('sequelize');
const User_Chat = sq.define('User_Chat', {
user_id: {
type: DataTypes.UUID,
allowNull: false
},
chat_id: {
type: DataTypes.UUID,
allowNull: false
}
}, {
tableName: 'users_chats'
});
module.exports = { User_Chat }
Initialization of all models:
// Imported models
const UserModel = require('./user').User;
const ChatModel = require('./chat').Chat;
const MessageModel = require('./message').Message;
// Imported junction model(s)
const User_ChatModel = require('./junctions/user_chat').User_Chat;
// Initialize models
const models = {
User: UserModel,
Chat: ChatModel,
Message: MessageModel,
User_Chat: User_ChatModel
};
console.log('n model index running n');
// Apply associations
Object.keys(models).forEach(modelName => {
console.log('nmodel name:', modelName, 'associating');
if (models[modelName].associate) {
models[modelName].associate(models);
}
});
module.exports = models;
I have tested querying the junction model directly, which works fine, and I have queried each model directly which also works fine. I added the junction model explicitly (the table was previously being created automatically through associations) after I couldn’t get Sequelize to recognize that I wanted it to use the junction table to match a user to the chats they are a part of. Previously,
it was assuming I wanted to join through the creator_id column. This was my attempt to solve that issue, but it did not work and returned the above error 🙂
My guess is that something is wrong with the way I initialize the models.
EXPECTED:
returning the data from the db with users and chats joined through users_chats where users.id = chats.user_id
PandaBearTellEm is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.