Related
i have a little problem. i'm making my backend in nodeJS, i use sequelize for implement database.
here the schema for DB:
DB Schema
my problem is in the mapPoint table and game table.
here is my server :
game.model.js
module.exports = (sequelize, Sequelize) => {
const Game = sequelize.define("games", {
name: {
type: Sequelize.STRING,
allowNull: false
},
latitude: {
type: Sequelize.FLOAT,
allowNull: false
},
longitude: {
type: Sequelize.FLOAT,
allowNull: false
}
});
return Game;
};
mapPoint.model.js
module.exports = (sequelize, Sequelize) => {
const MapPoint = sequelize.define("mapPoints", {
latitude: {
type: Sequelize.FLOAT,
allowNull: false
},
longitude: {
type: Sequelize.FLOAT,
allowNull: false
}
});
return MapPoint
};
my create function
exports.create = (req, res) => {
// Save User to Database
Game.create({
name: req.body.name,
latitude: req.body.latitude,
longitude: req.body.longitude,
userId: req.body.userId
})
.then((mapPoints) => {
console.log("------------- in .then")
if (req.body.mapPoints) {
console.log("------------- in if")
MapPoint.create(
console.log("------------- in create"),
{
latitude: req.body.latitude,
longitude: req.body.longitude
})
.then(() => {
console.log('xxxxx: ' + mapPoints);
game.addMapPoints(mapPoints)
.then(() => {
res.send({message: "MapPoint was added successfully"})
})
})
}
});
};
and relation 1:N between the game table and mapPoint table
// mapPoint -> game
db.game.hasMany(db.mapPoint, { as: "mapPoints"});
db.mapPoint.belongsTo(db.game, {
foreignKey: "gameId",
as: "game"
});
when i post json on postman, he send me error
postman: postman
the error:
/Users/arktik92/Desktop/CatServer/node_modules/sequelize/lib/instance-validator.js:50
throw new sequelizeError.ValidationError(null, this.errors);
^
ValidationError [SequelizeValidationError]: notNull Violation: mapPoints.latitude cannot be null,
notNull Violation: mapPoints.longitude cannot be null
at InstanceValidator._validate (/Users/arktik92/Desktop/CatServer/node_modules/sequelize/lib/instance-validator.js:50:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async InstanceValidator._validateAndRunHooks (/Users/arktik92/Desktop/CatServer/node_modules/sequelize/lib/instance-validator.js:60:7)
at async InstanceValidator.validate (/Users/arktik92/Desktop/CatServer/node_modules/sequelize/lib/instance-validator.js:54:12)
at async model.save (/Users/arktik92/Desktop/CatServer/node_modules/sequelize/lib/model.js:2368:7)
at async Function.create (/Users/arktik92/Desktop/CatServer/node_modules/sequelize/lib/model.js:1344:12) {
errors: [
ValidationErrorItem {
message: 'mapPoints.latitude cannot be null',
type: 'notNull Violation',
path: 'latitude',
value: null,
origin: 'CORE',
instance: mapPoints {
dataValues: {
id: null,
updatedAt: 2022-12-01T11:30:06.247Z,
createdAt: 2022-12-01T11:30:06.247Z
},
_previousDataValues: {},
uniqno: 1,
_changed: Set(0) {},
_options: {
isNewRecord: true,
_schema: null,
_schemaDelimiter: '',
attributes: undefined,
include: undefined,
raw: undefined,
silent: undefined
},
isNewRecord: true
},
validatorKey: 'is_null',
validatorName: null,
validatorArgs: []
},
ValidationErrorItem {
message: 'mapPoints.longitude cannot be null',
type: 'notNull Violation',
path: 'longitude',
value: null,
origin: 'CORE',
instance: mapPoints {
dataValues: {
id: null,
updatedAt: 2022-12-01T11:30:06.247Z,
createdAt: 2022-12-01T11:30:06.247Z
},
_previousDataValues: {},
uniqno: 1,
_changed: Set(0) {},
_options: {
isNewRecord: true,
_schema: null,
_schemaDelimiter: '',
attributes: undefined,
include: undefined,
raw: undefined,
silent: undefined
},
isNewRecord: true
},
validatorKey: 'is_null',
validatorName: null,
validatorArgs: []
}
]
}
[nodemon] app crashed - waiting for file changes before starting...
can you help me please ?
I have 1:n association User -> Cart, what I want is, I find User by Id then create Cart by that instance and then fill the product_id manually
I'm using sequelize
I have tried get,set,create from this association and none of them worked, it gave me this error
TypeError: user.createCart is not a function
at /home/horus/beginner-html-site-scripted/server/controllers/Cart.controller.ts:21:26
and this is my CartController:
const { product_id } = req.params;
const product = await ProductModel.findByPk(product_id);
if (!product) {
return res.status(401).json({ message: 'product not found' });
}
//#ts-ignore
const userData = req.user;
const user = await UserModel.findByPk(userData.user_id);
if (!user) return res.status(401).json({ message: 'user not found' });
const cart = await user.createCart();
res.status(200).json({ message: '', cartData: user.getCart() });
those are my Models:
Cart Class
export default class Cart
extends Model<InferAttributes<Cart>, InferCreationAttributes<Cart>>
implements CartInterface {
declare cart_id: CreationOptional<string>;
declare quantity: CreationOptional<number>;
declare user_id: string;
}
Cart.init(
{
cart_id: { type: UUID, defaultValue: UUIDV4, primaryKey: true },
quantity: { type: INTEGER, defaultValue: 1 },
user_id: {
type: UUID,
references: {
model: 'Users',
key: 'user_id',
},
},
},
{ sequelize: db, tableName: 'Carts' }
);
User Class
export default class User
extends Model<InferAttributes<User>, InferCreationAttributes<User>>
implements UserInterface {
declare user_id: CreationOptional<string>;
declare firstName: string;
declare lastName: string;
declare email: string;
declare password: string;
declare avatar: string;
declare verificationCode: CreationOptional<string>;
declare passwordResetCode: CreationOptional<string>;
declare verified: CreationOptional<boolean>;
declare isAdmin: CreationOptional<boolean>;
// timestamps!
// createdAt can be undefined during creation
declare createdAt: CreationOptional<Date>;
// updatedAt can be undefined during creation
declare updatedAt: CreationOptional<Date>;
declare createSession: HasManyCreateAssociationMixin<Session, 'user_id'>;
declare createCart: HasOneCreateAssociationMixin<CartModel>;
declare setCart: HasOneSetAssociationMixin<CartModel, 'cart_id'>;
declare getCart: HasOneGetAssociationMixin<CartModel>;
}
User.init(
{
user_id: {
primaryKey: true,
allowNull: false,
type: UUID,
defaultValue: UUIDV4,
},
firstName: { type: new STRING(128), allowNull: false },
lastName: { type: new STRING(128), allowNull: false },
email: { type: new STRING(128), allowNull: false, unique: true },
password: {
type: new STRING(128),
allowNull: false,
},
avatar: { type: new STRING(128), defaultValue: '' },
verificationCode: { type: UUID, allowNull: false, defaultValue: UUIDV4 },
passwordResetCode: { type: UUID, allowNull: false, defaultValue: '' },
verified: { type: BOOLEAN, defaultValue: false, allowNull: false },
isAdmin: { type: BOOLEAN, defaultValue: false, allowNull: false },
createdAt: DATE,
updatedAt: DATE,
},
{
sequelize: db,
tableName: 'Users',
}
);
user Data
User {
dataValues: {
user_id: '20b42b70-f777-420b-b15b-cbf3732c1a9b',
firstName: 'leo',
lastName: 'qal',
email: 't#gmail.com',
password: '$2.',
avatar: '',
verificationCode: '',
passwordResetCode: '',
verified: true,
isAdmin: true,
createdAt: 2022-02-17T16:49:40.000Z,
updatedAt: 2022-02-17T16:49:40.000Z
},
_previousDataValues: {
user_id: '20b42b70-f777-420b-b15b-cbf3732c1a9b',
firstName: 'leo',
lastName: 'qal',
email: 't#gmail.com',
password: '$2.',
avatar: '',
verificationCode: '',
passwordResetCode: '',
verified: true,
isAdmin: true,
createdAt: 2022-02-17T16:49:40.000Z,
updatedAt: 2022-02-17T16:49:40.000Z
},
uniqno: 1,
_changed: Set(0) {},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [
'user_id',
'firstName',
'lastName',
'email',
'password',
'avatar',
'verificationCode',
'passwordResetCode',
'verified',
'isAdmin',
'createdAt',
'updatedAt'
]
},
isNewRecord: false
}
Associations
UserModel.hasOne(CartModel, {
sourceKey: 'user_id',
foreignKey: 'user_id',
as: 'users',
});
CartModel.belongsTo(UserModel, {
foreignKey: 'cart_id',
as: 'carts',
});
//OneToMany Association
UserModel.hasMany(SessionModel, {
sourceKey: 'user_id',
foreignKey: 'user_id',
as: 'sessions', // this determines the name in `associations`!
});
CategoryModel.hasMany(ProductModel, {
sourceKey: 'category_id',
foreignKey: 'category_id',
as: 'products',
});
I am able to create records in my MySQL DB with sequelize and NodeJS.
But now I am trying to update records in my Database.
I have NodeJS as backend and my DB is MySql. Sequelize is my ORM. In Sequelize 5, I have a couple of classes: WorkOder, User (mechanic), Customer, Client and ExpertiseOffice. My datamodel is not complex, there are only 1:1 relations. A WorkOrder has one customer, one Client and one ExpertiseOffice.
I use Postman to test my api's. With creating a WorkOrder with some Customer fields included the workOrder is created but not the Customer.
My associations file looks like this:
const User = require('../models/user');
const WorkOrder = require('../models/work-order');
const Customer = require('../models/customer');
const Client = require('../models/client');
const ExpertiseOffice = require('../models/expertise-office');
WorkOrder.belongsTo(User, { foreignKey: 'mechanicId' });
WorkOrder.belongsTo(Client, { foreignKey: 'clientId' });
WorkOrder.belongsTo(Customer, { foreignKey: 'customerId' });
WorkOrder.belongsTo(ExpertiseOffice, { foreignKey: 'expertiseOfficeId' });
The WorkOrder model looks like this:
// WORK-ORDER MODEL
const Customer = require('./customer');
const Client = require('./client');
const ExpertiseOffice = require('./expertise-office');
const User = require('./user');
const Sequelize = require('sequelize');
const sequelize = require('../util/database');
const WorkOrder = sequelize.define('workOrders', {
id: {
type: Sequelize.UUID,
allowNull: false,
primaryKey: true,
},
projectNumber: {
type: Sequelize.INTEGER,
allowNull: true,
},
dateInspection: {
type: Sequelize.DATE,
allowNull: true,
},
mechanicId: {
type: Sequelize.UUID,
allowNull: true,
references: {
// User belongsTo WorkOrder 1:1
model: 'User',
key: 'id',
},
},
clientId: {
// Opdrachtgever
type: Sequelize.UUID,
allowNull: true,
references: {
// Client belongsTo WorkOrder 1:1
model: 'Client',
key: 'id',
},
},
customerId: {
// klant
type: Sequelize.UUID,
allowNull: true,
references: {
// Customer belongsTo WorkOrder 1:1
model: 'Customer',
key: 'id',
},
},
expertiseOfficeId: {
type: Sequelize.UUID,
allowNull: true,
references: {
// ExpertiseOffice belongsTo WorkOrder 1:1
model: 'ExpertiseOffice',
key: 'id',
},
},
leakageReason: {
type: Sequelize.STRING,
allowNull: true,
},
status: {
type: Sequelize.STRING,
allowNull: true,
},
// Timestamps
createdAt: Sequelize.DATE,
updatedAt: Sequelize.DATE,
});
module.exports = WorkOrder;
In the front end application only very limited fields are required because the front end user can add information about the customer, client etc. on a later moment.
My WorkOrder controller with the updatre workOrder code (not working properly) is looking like this.
exports.updateWorkOrder = (req, res, next) => {
console.log('####-in the updateWorkOrder endpoint!');
const workOrder = req.body;
console.log('####-put-workorder', workOrder);
WorkOrder.update(
workOrder,
{ where: { id: req.params.id } },
{ include: [User, Customer, Client, ExpertiseOffice] }
)
.then((result) => {
if (result) {
WorkOrder.findByPk(req.params.id).then((result) => {
console.log('####--result', result);
console.log('####-work-order updated!');
res.status(200).json({
message: 'Work order successfully updated!',
data: result,
});
});
}
})
.catch((err) => {
console.log('error', err);
res.status(500).json({
message: 'An error occurred',
err: err,
});
});
};
The workOrder data which is going into the update method looks like this:
####-in the updateWorkOrder endpoint!
####-put-workorder {
id: '29d9795d-ef7f-418e-a479-340cb7ee5509',
projectNumber: '123456',
dateInspection: null,
followupInspection: null,
clientPresent: null,
mechanicId: null,
clientId: '2c611177-48f6-48d2-a2d0-e7f6a93cc16b',
customerId: 'd53f56c7-9954-4e52-b8e2-de4d28229caf',
expertiseOfficeId: null,
leakageReason: 'issue with roof',
visibleWaterDamage: null,
visibleWaterDamagePeriod: null,
buildingType: null,
renovatedYear: null,
status: null,
createdAt: '2020-07-04T07:24:28.000Z',
updatedAt: '2020-07-04T07:25:03.000Z',
user: null,
customer: {
id: 'd53f56c7-9954-4e52-b8e2-de4d28229caf',
name: 'Customer One',
contactPerson: null,
companyName: null,
street: 'Street',
houseNumber: '1',
houseNumberExt: null,
zipCode: '91111',
city: 'LA',
phoneNumber: null
},
client: {
id: '2c611177-48f6-48d2-a2d0-e7f6a93cc16b',
name: 'Roof Inspectors',
contactPerson: null,
email: null,
phoneNumber: 'Roof Inspectors',
street: null,
houseNumber: null,
houseNumberExt: null,
zipCode: null,
city: null,
attribute: null
},
expertiseOffice: null
}
This is the correct updated information from the front end.
Now I don't get an error message from sequelize but the record is not updated.
The spooled result looks like this:
####--result workOrders {
dataValues: {
id: '29d9795d-ef7f-418e-a479-340cb7ee5509',
projectNumber: '123456',
dateInspection: null,
followupInspection: null,
clientPresent: null,
mechanicId: null,
clientId: '2c611177-48f6-48d2-a2d0-e7f6a93cc16b',
customerId: 'd53f56c7-9954-4e52-b8e2-de4d28229caf',
expertiseOfficeId: null,
leakageReason: 'issue with roof',
visibleWaterDamage: null,
visibleWaterDamagePeriod: null,
buildingType: null,
renovatedYear: null,
status: null,
createdAt: 2020-07-04T07:24:28.000Z,
updatedAt: 2020-07-04T08:06:47.000Z
},
_previousDataValues: {
id: '29d9795d-ef7f-418e-a479-340cb7ee5509',
projectNumber: '123456',
dateInspection: null,
followupInspection: null,
clientPresent: null,
mechanicId: null,
clientId: '2c611177-48f6-48d2-a2d0-e7f6a93cc16b',
customerId: 'd53f56c7-9954-4e52-b8e2-de4d28229caf',
expertiseOfficeId: null,
leakageReason: 'issue with roof',
visibleWaterDamage: null,
visibleWaterDamagePeriod: null,
buildingType: null,
renovatedYear: null,
status: null,
createdAt: 2020-07-04T07:24:28.000Z,
updatedAt: 2020-07-04T08:06:47.000Z
},
_changed: {},
_modelOptions: {
timestamps: true,
validate: {},
freezeTableName: false,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: { id: '29d9795d-ef7f-418e-a479-340cb7ee5509' },
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: { plural: 'workOrders', singular: 'workOrder' },
omitNull: false,
sequelize: Sequelize {
options: [Object],
config: [Object],
dialect: [MysqlDialect],
queryInterface: [QueryInterface],
models: [Object],
modelManager: [ModelManager],
connectionManager: [ConnectionManager],
importCache: {}
},
hooks: {}
},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [
'id',
'projectNumber',
'dateInspection',
'followupInspection',
'clientPresent',
'mechanicId',
'clientId',
'customerId',
'expertiseOfficeId',
'leakageReason',
'visibleWaterDamage',
'visibleWaterDamagePeriod',
'buildingType',
'renovatedYear',
'status',
'createdAt',
'updatedAt'
]
},
isNewRecord: false
}
Can anybody please help me? I have no clue why the records is not updated.
Many thanks in advance.
Pete
What's wrong with the api or router? I definitely included the user model Why is no user information included? Below is the api logic for loading an existing post.
Since the author information is also required, the user model information is included using the include syntax below.
User information is not printed.
What is the reason?
git
https://github.com/hyunsokstar/node_bird_22
api code
router.get('/', async (req, res, next) => { // GET /api/posts
try {
const posts = await db.Post.findAll({
include: [{
model: db.User,
attributes: ['id', 'nickname'],
}],
order: [['createdAt', 'DESC']], // DESC는 내림차순, ASC는 오름차순
});
console.log("posts : ", posts);
res.json(posts);
} catch (e) {
console.error(e);
next(e);
}
});
model
// back\models\post.js
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define('Post', { // 테이블명은 posts
content: {
type: DataTypes.TEXT, // 매우 긴 글
allowNull: false,
},
}, {
charset: 'utf8mb4', // 한글+이모티콘
collate: 'utf8mb4_general_ci',
});
Post.associate = (db) => {
db.Post.belongsTo(db.User); // 테이블에 UserId 컬럼이 생겨요
db.Post.hasMany(db.Comment);
db.Post.hasMany(db.Image);
// 릴레이션 관계 추가
db.Post.belongsTo(db.Post, { as: 'Retweet' }); // RetweetId 컬럼 생성
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag' });
db.Post.belongsToMany(db.User, { through: 'Like', as: 'Likers' });
};
return Post;
};
result
Post {
dataValues:
{ id: 21,
content: 'write test',
createdAt: 2019-11-07T09:43:00.000Z,
updatedAt: 2019-11-07T09:43:00.000Z,
UserId: 1,
RetweetId: null,
User: [User] },
_previousDataValues:
{ id: 21,
content: 'write test',
createdAt: 2019-11-07T09:43:00.000Z,
updatedAt: 2019-11-07T09:43:00.000Z,
UserId: 1,
RetweetId: null,
User: [User] },
_changed: {},
_modelOptions:
{ timestamps: true,
validate: {},
freezeTableName: false,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: null,
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: [Object],
omitNull: false,
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
sequelize: [Sequelize],
hooks: {} },
_options:
{ isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
include: [Array],
includeNames: [Array],
includeMap: [Object],
includeValidated: true,
attributes: [Array],
raw: true },
isNewRecord: false,
User:
User {
dataValues: [Object],
_previousDataValues: [Object],
_changed: {},
_modelOptions: [Object],
_options: [Object],
isNewRecord: false } } ]
const where = {};
let options = { where };
options.include = [
{
model: db.User,
attributes: ['id', 'nickname'],
},
];
options.order = [['createdAt', 'DESC']];
const posts = await db.Post.findAll(options);
Try this it will help
I have tables like Medics, MedicalSpecialties and Users. Models are define like:
Users Model
const Database = require('../sequelize');
const UserModel = Database
.getInstance()
.define('users', {
UserId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
primaryKey: true,
autoIncrement: true
},
FirstName: Database.FIELD_TYPE_ENUM.STRING,
MiddleName: Database.FIELD_TYPE_ENUM.STRING,
LastName: Database.FIELD_TYPE_ENUM.STRING,
SecondLastName: Database.FIELD_TYPE_ENUM.STRING,
ID: Database.FIELD_TYPE_ENUM.STRING,
Email: Database.FIELD_TYPE_ENUM.STRING,
Password: Database.FIELD_TYPE_ENUM.STRING,
CellPhoneNumber: Database.FIELD_TYPE_ENUM.STRING,
OtherPhoneNumber: Database.FIELD_TYPE_ENUM.STRING,
Deleted: Database.FIELD_TYPE_ENUM.BOOLEAN
});
module.exports = UserModel;
Medical Specialties Model
const Database = require('../sequelize');
const MedicalSpecialtyModel = Database
.getInstance()
.define('medicalspecialties', {
MedicalSpecialtyId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
primaryKey: true,
autoIncrement: true
},
Description: Database.FIELD_TYPE_ENUM.STRING,
CreatedUserId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
references: {
model: 'users',
key: 'UserId'
}
},
UpdatedUserId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
references: {
model: 'users',
key: 'UserId'
},
allowNull: true
},
createdAt: Database.FIELD_TYPE_ENUM.DATETIME,
updatedAt: Database.FIELD_TYPE_ENUM.DATETIME
});
module.exports = MedicalSpecialtyModel;
Medics Model
const Database = require('../sequelize');
const MedicModel = Database
.getInstance()
.define('medics', {
MedicId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
primaryKey: true,
autoIncrement: false,
references: {
model: 'users',
key: 'UserId'
}
},
MedicalSpecialtyId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
references: {
model: 'medicalspecialties',
key: 'MedicalSpecialtyId'
}
},
Code: Database.FIELD_TYPE_ENUM.STRING,
CreatedUserId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
references: {
model: 'users',
key: 'UserId'
}
},
UpdatedUserId: {
type: Database.FIELD_TYPE_ENUM.INTEGER,
references: {
model: 'users',
key: 'UserId'
},
allowNull: true
}
});
module.exports = MedicModel;
What I want to do is to get results with object parent child Representation like
[
{
"MedicId": 1,
"Code": "test1",
"user": {
"UserId": 4,
"FirstName": "John",
"MiddleName": null,
"LastName": "Doe",
"SecondLastName": null,
},
"medicalspecialty": {
"MedicalSpecialtyId": 3,
"Description": "Doctor"
}
}
]
But instead I'm getting this result:
[
{
"MedicId": 1,
"Code": "test1",
"user.UserId": 4,
"user.FirstName": "John",
"user.MiddleName": null,
"user.LastName": "Doe",
"user.SecondLastName": null,
"medicalspecialty.MedicalSpecialtyId": 3,
"medicalspecialty.Description": "Doctor"
}
]
This is how I'm pulling data:
static getAllMedics() {
MedicModel.belongsTo(MedicalSpecialtyModel, {
foreignKey: 'MedicalSpecialtyId'
});
MedicModel.belongsTo(UserModel, {
foreignKey: 'UserId'
});
UserModel.belongsTo(MedicModel);
MedicalSpecialtyModel.hasMany(MedicModel);
const attributes = ['MedicId', 'Code'];
return MedicModel.findAll({
attributes,
include: [{
model: UserModel,
attributes: ['UserId', 'FirstName', 'MiddleName', 'LastName', 'SecondLastName'],
where: {
Deleted: false
},
required: true,
nested: true
}, {
model: MedicalSpecialtyModel,
attributes: ['MedicalSpecialtyId', 'Description'],
required: true,
nested: true
}],
raw: true
});
}
Hope you can help me.
The raw property on a find call flattens the structure.
Basically do a find without raw: true.
You could get more info about it here
At the end it was my error.
When initializing Sequelize I had added the option row: true.
new Sequelize(..., {
...,
row: true
})
My apologies.