I was trying to connect and get data from oracle database using sequelize, but it was returning an error Cannot read properties of undefined (reading 'length'): undefined
Here is the code :
Connection
import { Sequelize, DataTypes } from "sequelize";
import _projects from "../models/projects.js";
export const getProjects = async (req, res, next) => {
var conn = new Sequelize({
dialect: 'oracle',
username: dbAdmin,
password: dbPass,
dialectOptions: { connectString: connStr } // also tried { connectionString: connStr }
});
function initModel(connection) {
const projects = _projects.init(connection, DataTypes);
return { projects };
}
var db = initModel(conn);
const all_projects = await db.projects.findAll()
console.log("all_projects", all_projects.rows); // Cannot read properties of undefined (reading 'length'): undefined
}
projects.js
import _sequelize from 'sequelize';
const { Model, Sequelize } = _sequelize;
export default class projects extends Model {
static init(sequelize, DataTypes) {
return super.init({
id: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true
},
credat: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: Sequelize.fn('getdate')
},
description: {
type: DataTypes.STRING(1024),
allowNull: true
},
picture: {
type: DataTypes.STRING(255),
allowNull: true
},
settings: {
type: DataTypes.TEXT,
allowNull: true
},
is_deleted: {
type: DataTypes.INTEGER,
allowNull: true
}
}, {
sequelize,
tableName: 'projects',
schema: 'dbo',
timestamps: false,
});
}
}
It seems like you confused findAll with findAndCountAll which returns rowa and count and also you didn't indicate any parameters at all (which can lead to this error with undefined) in findAll:
Compare:
const all_projects = await db.projects.findAll({})
console.log("all_projects", all_projects);
and
const a_page_of_projects = await db.projects.findAndCountAll({
limit: 10,
offset: 0
})
console.log("a_page_of_projects rows", a_page_of_projects.rows);
console.log("a_page_of_projects count", a_page_of_projects.count);
Related
I am new to sequelize orm.
While developing backend with express, sequelize and mssql, I created models with sequelize-cli.
Before I have index.js file and new models created by seqeulize-cli command 'sequelize init' and 'sequelize model:generate..", I had no issue.
But as I start the server I encountered the error saying "TypeError: Class constructor model cannot be invoked without 'new'".
I have not touched index.js file and the new model generated by sequelize-cli is class-basis.
I tried to change class-basis model to sequelize.define() but still get the same error.
Please help me resolve the issue.
Thanks!!
Here is my code.
index.js
"use strict";
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const process = require("process");
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || "development";
const config = require(__dirname + "/../config/config.json")[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
} else {
}
fs.readdirSync(__dirname)
.filter((file) => {
return (
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
);
})
.forEach((file) => {
console.log("##########", path.join(__dirname, file))
const model = require(path.join(__dirname, file))(
sequelize,
Sequelize.DataTypes
);
db[model.name] = model;
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
GroupCode.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class GroupCode extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate({ CommonCode }) {
// define association here
this.hasMany(CommonCode);
}
}
GroupCode.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
description: {
type: DataTypes.STRING,
},
active: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
createdBy: {
type: DataTypes.STRING,
},
updatedBy: {
type: DataTypes.STRING,
},
},
{
sequelize,
modelName: "GroupCode",
}
);
return GroupCode;
};
CommonCode.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class CommonCode extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate({ GroupCode }) {
// define association here
this.belongsTo(GroupCode, {
foreignKey: { name: "groupCodeId", allowNull: false },
});
}
}
CommonCode.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
value: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
seq: {
type: DataTypes.INTEGER,
default: 1,
},
active: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
createdBy: {
type: DataTypes.STRING,
},
updatedBy: {
type: DataTypes.STRING,
},
},
{
sequelize,
modelName: "CommonCode",
}
);
return CommonCode;
};
Resolve the error that appears when start the server.
I have 2 tables, users and users_signature where the signature takes several applications and I need to make a select according to the application.
Models:
user
const { INTEGER } = require('sequelize');
const Sequelize = require('sequelize');
const database = require('../../config/db');
const User_has_signature = require('./user_has_signature');
const Usuario = database.define('usuario', {
usu_id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
usu_rg: {
type: Sequelize.STRING,
},
},
{
freezeTableName: true,
createdAt: false,
updatedAt: false,
});
User.hasMany(User_has_signature, {as: 'user_has_signature'});
module.exports = User;
User_has_signature
const { INTEGER } = require('sequelize');
const Sequelize = require('sequelize');
const database = require('../../config/db');
const User_has_signature = database.define('user_has_signature', {
usu_has_signature_id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
user_usu_id: {
type: Sequelize.STRING,
},
signature_aplicativo_signature_aplicativo_id: {
type: Sequelize.STRING,
},
signature_type_signature_type_id: {
type: Sequelize.STRING,
},
},
{
freezeTableName: true,
createdAt: false,
updatedAt: false,
});
User_has_signature.associate = (models) => {
User_has_signature.belongsTo(models.User,
{ foreignKey: 'user_usu_id', as: 'users' });
};
module.exports = User_has_signature;
Controller
UserController
const User = require("../../model/user/user")
const User_has_signature = require("../../model/user/user_has_signature")
async index(req, res){
const user = await User.findAll({
include: [{
model: User_has_signature,
foreignKey: 'user_usu_id',
through: {
where: {signature_ttype_signature_type_id: 3}
}
}]
})
res.status(200).json(user)
return
}
The error that is returning to me in the terminal is: (node:15168)
UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError:
user_has_signature is associated to usuario using an alias. You must
use the 'as' keyword to specify the alias within your include
statement
I think you have to specify the alias you have given when writing your query :
include: [{
model: User_has_signature,
foreignKey: 'user_usu_id',
as : 'users'
through: {
where: {signature_ttype_signature_type_id: 3}
}]
Either way I'm using Sequelize more in Typescript, so I'm not sure of the syntax.
The way it handles One to Many relationship isn't the clearest I've seen (Like Symfony or Spring)
I have created number of function in the user model which are both instance and class methods. But when i am calling class method findMyMobile() from a controller it is giving 'not a function' error. I tried display it inside the controller but it seems it is undefined there.
model/user.js
const { Sequelize, sequelize } = require('../db/sequelize');
const jwt = require('jsonwebtoken');
const Model = Sequelize.Model;
class User extends Model {}
User.init({
id:{
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
allowNull: false
},
mobile_number:{
field:'mobile_number',
type: Sequelize.BIGINT(10),
unique:true,
allowNull: false,
is:/^[1-9]\d{9}$/g,
},
type:{
type: Sequelize.ENUM('0','1','2'),
allowNull: false,
defaultValue: '1',
},
otp:{
type: Sequelize.STRING,
},
createdAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW
}
},{ sequelize,
modelName:'user',
classMethods:{
findByMobile: function(){
var User = this;
return User.findOne({'mobile_number':data['mobile_number']}).then(user => {
return new Promise((resolve,reject)=>{
if(user)
resolve(user);
else
reject(new Error('No user found'));
});
}).catch(err=>{
return Promise.reject(new Error('Database error'));
})
}
}
})
User.sync();
module.exports = {
User
}
controller/login.js
const { User } = require('../model/user');
const _ = require('lodash');
exports.login = (req, res) => {
const mobile = _.pick(req.body, ['mobile_number']);
console.log(typeof User.findByMobile);
User.findByMobile(mobile).then((user) => {
console.log(user);
}).catch(err => {
var response = {
status: 'failure',
message: err.message
}
res.send(response);
});
};
ERROR:
TypeError: User.findByMobile is not a function
Since sequelize v4 classMethods and instanceMethod are removed from the configuration options : https://sequelize.org/v4/manual/tutorial/upgrade-to-v4.html#config-options
You have two ways to define them
class User extends Model {
//Class Method
static findByMobile() {}
//Instance Method
findByMobile() {}
}
OR
class User extends Model { }
//Class Method
User.findByMobile = function() {}
//Instance Method
User.prototype.findByMobile = function() {}
I think you have the export wrong. See this example for reference.
module.exports = {
getName: () => {
return 'Jim';
},
getLocation: () => {
return 'Munich';
},
dob: '12.01.1982',
};
Then on the import file:
const { getName, dob } = require('./user');
console.log(
`${getName()} was born on ${dob}.`
);
What I do suggest is export the function itself. See link below for ref:
What is the purpose of Node.js module.exports and how do you use it?
i'm using NodeJS & Sequelize for a school project and i'm struggling on making associations w/ sequelize work. I tried a couple of things before but nothing that made my day.
Basically the thing is that a user can have several playlists (hasMany).
And a playlist belongs to a user (belongsTo).
My error is:
Association with alias "playlist" does not exist on users
Here are my models:
/* USER MODEL */
const Sequelize = require('sequelize');
const { db } = require('../utils/db');
const User = db.define('users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
userID: {
type: Sequelize.INTEGER,
allowNull: false,
field: 'user_id',
},
firstName: {
type: Sequelize.STRING,
field: 'first_name',
allowNull: false,
},
}, {
underscored: true,
tableName: 'users',
freezeTableName: true, // Model tableName will be the same as the model name
});
module.exports = {
User,
};
/* PLAYLIST MODEL */
const sequelize = require('sequelize');
const { db } = require('../utils/db');
const Playlist = db.define('playlist', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: sequelize.INTEGER,
},
name: {
type: sequelize.STRING,
field: 'name',
allowNull: false,
},
coverUrl: {
type: sequelize.STRING,
field: 'cover_url',
allowNull: true,
},
ownerId: {
type: sequelize.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'user_id',
},
},
}, {
underscored: true,
tableName: 'playlist',
freezeTableName: true,
});
module.exports = {
Playlist,
};
Here is how i load my models:
const { Credentials } = require('./credentials');
const { User } = require('./users');
const { Playlist } = require('./playlist');
function loadModels() {
User.associate = (models) => {
User.hasMany(models.Playlist, { as: 'playlist' });
};
Playlist.associate = (models) => {
Playlist.belongsTo(models.User, { foreignKey: 'owner_id', as: 'owner' });
};
Credentials.sync({ force: false });
User.sync({ force: false });
Playlist.sync({ force: false });
}
module.exports = {
loadModels,
};
And finally here is my query where i get this error:
const express = require('express');
const { auth } = require('../../middlewares/auth');
const { Playlist } = require('../../models/playlist');
const { User } = require('../../models/users');
const router = express.Router();
router.get('/playlist', [], auth, (req, res) => {
User.findOne({
where: { userID: req.user.user_id }, include: 'playlist',
}).then((r) => {
console.log(r);
});
});
module.exports = router;
I'm trying to get all the playlist that belongs to a user.
I removed all the useless code (jwt check etc..)
So when i'm doing a get request on /playlist I get:
Unhandled rejection Error: Association with alias "playlist" does not exist on users.
I understand the error but don't understand why i get this.
What did I miss, any ideas ?
Thanks,
I finally fixed it by re-make all my models and definitions with migrations.
I had the same problem and the solution was that Sequelize pluralize the models name so in my case "playlist" does not exist on users because Sequelize pluralized my model so I had to put "Playlists" instead.
I'm totally newbie with Sequelize and I'm getting the next error when I run my application and sync my tables:
TypeError: UserModel.hasMany is not a function
at Object.<anonymous> (/home/josecarlos/Workspace/nodejs/remote-roofing/src/server/models/users.js:46:11)
at Module._compile (internal/modules/cjs/loader.js:816:30)
at Module._compile (/home/josecarlos/Workspace/nodejs/remote-roofing/node_modules/pirates/lib/index.js:99:24)
at Module._extensions..js (internal/modules/cjs/loader.js:827:10)
at Object.newLoader [as .js] (/home/josecarlos/Workspace/nodejs/remote-roofing/node_modules/pirates/lib/index.js:104:7)
I've got two tables only, so I have defined two models. One for each one and try to relationship between them.
user.js
import ProjectModel from "./projects";
const UserModel = (sequelize, type) => {
return sequelize.define("user", {
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
email: {
type: type.STRING,
allowNull: false,
isEmail: {
msg: "The format of the e-mail is not correct"
},
validate: {
notNull: {
msg: "E-mail cannot be empty"
}
}
},
name: {
type: type.STRING,
is: /^[a-zA-Z ]+$/i,
allowNull: false,
validate: {
notNull: {
msg: "Name cannot be empty"
}
}
},
surname: {
type: type.STRING,
is: /^[a-zA-Z ]+$/i,
allowNull: false,
validate: {
notNull: {
msg: "Surname cannot be empty"
}
}
}
})
};
UserModel.hasMany(ProjectModel, { foreingKey: "userID", sourceKey: "id"});
ProjectModel.belongsTo(UserModel, { foreingKey: "userID", sourceKey: "id"});
module.exports.UserModel = UserModel;
project.js
import UserModel from "./users";
const ProjectModel = (sequelize, type) => {
return sequelize.define("project", {
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
name: {
type: type.STRING,
is: /^[a-zA-Z ]+$/i,
allowNull: false,
validate: {
notNull: {
msg: "Name cannot be empty"
}
}
},
body: {
type: type.TEXT,
allowNull: false,
validate: {
notNull: {
msg: "Body cannot be empty"
}
}
},
status: {
type: type.ENUM("active", "inactive", "declined", "completed"),
allowNull: false,
validate: {
notNull: {
msg: "Status cannot be empty"
}
}
},
userID: {
type: type.INTEGER,
allowNull: false,
validate: {
notNull: {
msg: "userID cannot be empty"
}
}
}
})
};
module.exports.ProjectModel = ProjectModel;
This two models are create from db.js:
import Sequelize from "sequelize";
import UserModel from "./models/users";
import ProjectModel from "./models/projects";
//It's mandatory to import dotenv in each file where we can use enviroment variables
import config from "dotenv";
config.config();
const sequelize = new Sequelize(process.env.DDBB_NAME, process.env.DDBB_USER,process.env.DDBB_PSWD, {
host: process.env.DDBB_HOST,
port: process.env.DDBB_PORT,
define: {
//freezeTableName: true, /**Don't add 's to the end of each table/model */
//timestamps: false, /**Don't add fields createdAt and updatedAt */
},
dialect: "postgres",
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
);
const User = UserModel(sequelize, Sequelize);
const Project = ProjectModel(sequelize, Sequelize);
sequelize.sync({force: false}).then(() => {
console.log("Tables syncronized!!!")
})
module.exports = {
User,
Project
};
This file is required when I run the application. And I've got the error that I have showned before.
What am I doing wrong?
Edit I:
I have modified db.js file and it doesn't work to me. I've got the same error. I don't know how been called the models :(((((
import Sequelize from "sequelize";
import UserModel from "./models/users";
import ProjectModel from "./models/projects";
import fs from "fs";
import path from "path";
//It's mandatory to import dotenv in each file where we can use enviroment variables
import config from "dotenv";
config.config();
const sequelize = new Sequelize(process.env.DDBB_NAME, process.env.DDBB_USER,process.env.DDBB_PSWD, {
host: process.env.DDBB_HOST,
port: process.env.DDBB_PORT,
define: {
//freezeTableName: true, /**Don't add 's to the end of each table/model */
//timestamps: false, /**Don't add fields createdAt and updatedAt */
},
dialect: "postgres",
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
);
let db = {
sequelize,
Sequelize,
models: {}
}
//Register Models
const models = path.join(__dirname, "models");
fs
.readdirSync(models)
.filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')
})
.forEach(function (file) {
var model = sequelize['import'](path.join(models, file))
db[model.name] = model
})
Object.keys(db).forEach(function (modelName) {
if (db[modelName].associate) {
db[modelName].associate(db)
}
})
db.sequelize.sync({force: false}).then(() => {
console.log("Tables syncronized!!!")
})
module.exports.db = db;
Edit II:
Now, I've got this error:
/home/josecarlos/Workspace/nodejs/remote-roofing/src/server/models/users.js:9
var UserModel = _db["default"].sequelize.define("user", {
^
TypeError: Cannot read property 'define' of undefined
at Object.<anonymous> (/home/josecarlos/Workspace/nodejs/remote-roofing/src/server/models/users.js:4:32)
db.js
import Sequelize from "sequelize";
import UserModel from "./models/users";
import ProjectModel from "./models/projects";
import fs from "fs";
import path from "path";
//It's mandatory to import dotenv in each file where we can use enviroment variables
import config from "dotenv";
config.config();
const sequelize = new Sequelize(process.env.DDBB_NAME, process.env.DDBB_USER,process.env.DDBB_PSWD, {
host: process.env.DDBB_HOST,
port: process.env.DDBB_PORT,
define: {
//freezeTableName: true, /**Don't add 's to the end of each table/model */
//timestamps: false, /**Don't add fields createdAt and updatedAt */
},
dialect: "postgres",
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
);
let db = {
sequelize: sequelize,
Sequelize: Sequelize,
models: {}
}
//Register Models
const models = path.join(__dirname, "models");
fs
.readdirSync(models)
.filter(function (file) {
console.log("file: " + file);
return (file.indexOf('.') !== 0) && (file.slice(-3) === '.js')
})
.forEach(function (file) {
var model = sequelize['import'](path.join(models, file))
db[model.name] = model
})
Object.keys(db).forEach(function (modelName) {
if (db[modelName].associate) {
db[modelName].associate(db)
}
})
db.sequelize.sync({force: false}).then(() => {
console.log("Tables syncronized!!!")
})
module.exports.db = db;
users.js
import Sequelize from "sequelize";
import db from "../db";
const UserModel = db.sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
email: {
type: Sequelize.STRING,
allowNull: false,
isEmail: {
msg: "The format of the e-mail is not correct"
},
validate: {
notNull: {
msg: "E-mail cannot be empty"
}
}
},
name: {
type: Sequelize.STRING,
is: /^[a-zA-Z ]+$/i,
allowNull: false,
validate: {
notNull: {
msg: "Name cannot be empty"
}
}
},
surname: {
type: Sequelize.STRING,
is: /^[a-zA-Z ]+$/i,
allowNull: false,
validate: {
notNull: {
msg: "Surname cannot be empty"
}
}
}
})
UserModel.associate = (models) => {
UserModel.hasMany(models.ProjectModel, {
foreignKey: "userID"
})
}
module.exports.UserModel = UserModel;
project.js
import Sequelize from "sequelize";
import db from "../db";
const ProjectModel = db.sequelize.define("project", {
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
name: {
type: type.STRING,
is: /^[a-zA-Z ]+$/i,
allowNull: false,
validate: {
notNull: {
msg: "Name cannot be empty"
}
}
},
body: {
type: type.TEXT,
allowNull: false,
validate: {
notNull: {
msg: "Body cannot be empty"
}
}
},
status: {
type: type.ENUM("active", "inactive", "declined", "completed"),
allowNull: false,
validate: {
notNull: {
msg: "Status cannot be empty"
}
}
},
userID: {
type: type.INTEGER,
allowNull: false,
validate: {
notNull: {
msg: "userID cannot be empty"
}
}
}
});
ProjectModel.associate = (models) => {
ProjectModel.belongsTo(models.UserModel, {
foreignKey: "userID"
})
}
module.exports.ProjectModel = ProjectModel;
Sorry, but I don't understand anything ... :((
Edit III:
I have checked the keys of db in user.js and I've got nothing, so it's right that I've got thi error, but ... Why have db nothing?
[nodemon] starting `babel-node src/server/server.js`
db:
Your issue is that UserModel in user.js is as a function that returns a sequalize definition.
In the same file you are trying to call UserModel.hasMany on the function that returns your model object instead of on the model object itself.
You probably just want to remove the wrapping function and assign the sequalize object to UserModel directly.
const UserModel = sequelize.define("user", {
...
or move the calls on UserModel into the function.
const model = sequelize.define("user", {
...
});
model.hasMany(ProjectModel, { foreingKey: "userID", sourceKey: "id"});
model.belongsTo(UserModel, { foreingKey: "userID", sourceKey: "id"});
return model;
};
module.exports.UserModel = UserModel;