Where should I store my data models? - node.js

I use sqlight to create a datamodel in a node-module:
database.js:
var Sequelize = require('sequelize'),
settings = require('./settings.js').settings,
sequelize = new Sequelize(settings.database),
//Datamodel
User = sequelize.define('user', {
authID: Sequelize.STRING,
name: Sequelize.STRING,
}),
UserAttribute = sequelize.define('userAttributes', {
name: Sequelize.STRING,
value: Sequelize.STRING,
}),
Hail = sequelize.define('hail', {
lat: Sequelize.INTEGER,
lon: Sequelize.INTEGER,
});
UserAttribute.belongsTo(User);
Hail.belongsTo(User, {as: 'driver'});
Hail.belongsTo(User, {as: 'rider'});
sequelize.sync(settings.sync).then(function() {
return User.create({});
}).then(function(driver) {
console.log(driver.get({
plain: true
}));
});
This works fine, but what if I want to access the models in another part of my application, like if I would like to create a user inside a controller. Where should i store them and what would be a good way of doing that?

A common way of organizing apps having Sequelize models is creating a models package with index.js inside handling association and reading the models inside the package directory. Example:
sequelize/express-example
Also see #Farm's answer in this thread:
How to organize a node app that uses sequelize?

Related

Nodejs and Sequelize Limitations regarding creating dynamic models

I've a simple question related to my scenario. I've a react frontend where admin have a form to define it's own sign up form for the users.
Admin will send a set of fields with it's data types
Backend NodeJs will take those fields and run some script/function to create table in a database with the data types accordingly
It also needs to create a model for the respective table dynamically
I'm just finding a way to get it done. Any alternate solution is welcomed or any suggestions to refine my scenario?
Thanks in advance
You can just map all indicated fields into field definitions for Sequielize like:
fieldName: {
field: 'field_name',
type: DataTypes.TEXT,
allowNull: false
},
and call sequelize.define which will return you a Sequilize model that you can use to execute queries:
// NOTE "sequelize" should be an instance of Sequelize, i.e. an existing connection.
function registerModel(tableName, modelName, fields) {
const model = sequelize.define(modelName, {
...fields
}, {
tableName: tableName,
timestamps: false,
});
return model;
}
Register a new model:
const fields = [{
fieldName: {
field: 'field_name',
type: DataTypes.TEXT,
allowNull: false
},
}]
const newModel = registerModel('some_table', 'someModel', fields);
Use the registered model:
const items = await newModel.findAll({
where: {
// some conditions
}
})

Sequelize magic method not found using Express and Node.JS

I'm coding an application using Sequelize, Express and Node.JS; after set a OneToMany relationship between User and Product, just like this:
app.js:
Product.belongsTo(User, { constraints: true, onDelete: 'CASCADE' });
User.hasMany(Product);
and from a controller called admin.js I'm trying to create a new Product using a magic method:
admin.js:
exports.postAddProduct = (req, res, next) => {
const title = req.body.title;
const imageUrl = req.body.imageUrl;
const price = req.body.price;
const description = req.body.description;
req.user.createProduct({
title: title,
imageUrl: imageUrl,
price: price,
description: description
})
.then((result) => {
console.log("Record successfully created");
return res.redirect("/admin/products");
})
.catch((err) => {
console.log(err);
});
};
postAddProduct is triggered after submit a form, the error I'm getting is this:
So, my question is: based on sequelize's official documentation, after define a relationship I can use methods for create, edit o search an entity, what am I missing to get access to these methods?
thanks for your comments
even though my model is called Product, the table's name is newproducts, so, in order to solve this I made this change:
req.user.createNewproduct({
title: title,
imageUrl: imageUrl,
price: price,
description: description })
After this, problem solved
Nice to see someone else taking Max's Node.js course!
I had this same problem. For me, it stemmed from the fact that I defined how my id column works differently. Instead of this...
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
...I did this...
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
and utilized the uuid package to make unique Product and User IDs. Because of this, I had to update how I defined my SQL relations in app.js:
Product.belongsTo(User, { constraints: true, onDelete: "CASCADE" });
User.hasMany(Product, { foreignKey: "id" });
So if you're using a custom ID generator or something, make sure to specify that you are in the options object and the function should appear!
You can read more about this in the docs: https://sequelize.org/docs/v6/core-concepts/assocs/#defining-the-sequelize-associations
Hope this helps!

Sequelize() doesn't return an instance of sequelize

I recently started using Sequelize to get a model of my postgresql database.
To map the database I am using sequelize-auto.
I was able to create an auto generated mapping of my db using sequelize-auto when I sent my arguments this way to its constructor:
init.js
let sequelizeAutoInstance = new SequelizeAuto(dbName,username,password,options)
But it doesn't work when I try to send an instance of Sequelize this way:
new-init.js
let sequelizeInstance = new Sequelize(sequelizeOptions);
sequelizeAutoInstance = new SequelizeAuto(sequelizeInstance)
Looking into sequelize-auto ctor I saw it runs those lines:
if (database instanceof Sequelize) {
this.sequelize = database;
}
but the instance returning form new Sequelize doesn't return an instance of Sequelize.
What did I miss?
thanks
If I got you correct. You need to pass an instance of sequelize to your models. If you are using extension models you can simply pass in the instance into the init options.
const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = require("../your/db/file");
class User extends Model {}
User.init({
// Model attributes are defined here
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull defaults to true
}
}, {
// Other model options go here
sequelize, // We need to pass the connection instance
modelName: 'User' // We need to choose the model name
});
if its functional then
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = require("../your/db/file");
const User = sequelize.define('User', {
// Model attributes are defined here
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull defaults to true
}
}, {
// Other model options go here
});
All this can be found in the Sequelize models documentation

Node js and Code First

I've worked on Entity Framework with Code First approach. Now I am learning Node.js I wonder is there a way to make the same code first approach using Node.js and some libraly? I am thinking of using MySql as database.
You can look into Sequelize. Example of usage from the home page (I added comments to relate to Code First):
var Sequelize = require('sequelize');
// define your "context"
var sequelize = new Sequelize('database', 'username', 'password');
// define your "entities"
var User = sequelize.define('user', {
username: Sequelize.STRING,
birthday: Sequelize.DATE
});
// use them
sequelize.sync().then(function() {
return User.create({
username: 'janedoe',
birthday: new Date(1980, 6, 20)
});
}).then(function(jane) {
console.log(jane.get({
plain: true
}));
});

Nodejs with Sequelizejs using separate files per model

This is an embarrassingly beginner question, but I just want to settle my worries about Sequelizejs. I want to split out each model into its own file to keep my source organized. In order to do that I need to require("sequelize') and var sequelize = new Sequelize('DB-Name', 'DB-User', 'DB-Password'); at the start of each file.
My question is, will that create a new connection to the database per model, or will it just keep re-using the same connection? Should I abandon the whole concept of "one model per file" and just create a master Models.js file?
I am very new to Node and am still getting used to its conventions. Thanks for the help!
Every model is defined as its own module, which you export:
module.exports = function(sequelize, DataTypes){
return sequelize.define('Brand', {
name: {
type: DataTypes.STRING,
unique: true,
allowNull: false },
description: {
type: DataTypes.TEXT,
allowNull: false },
status: {
type: DataTypes.INTEGER,
unique: false,
allowNull: true }
})
};
Then simply import the module when you initialize Sequelize (and you can import many models here):
var Sequelize = require("sequelize");
var config = require("../../config/config.js");
var sequelize = new Sequelize(config.database, config.username, config.password,
{ dialect: config.dialect, host: config.host, port: config.port,
omitNull: true, logging: false });
var Brand = require("./Brand").Brand;
You can read up more on modules at http://nodejs.org/api/modules.htm but the example above should get you started.
In case if one wants to use EcmaScript 6 approach there is great example with explanation in Sequelize documentation here.
// in your server file - e.g. app.js
const Project = sequelize.import(__dirname + "/path/to/models/project")
// The model definition is done in /path/to/models/project.js
// As you might notice, the DataTypes are the very same as explained above
module.exports = (sequelize, DataTypes) => {
return sequelize.define("project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
}
The import method can also accept a callback as an argument.
sequelize.import('project', (sequelize, DataTypes) => {
return sequelize.define("project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
})

Resources