createdAt cannot be an array or an object - node.js

Can someone help me I'm having problems inserting a record in the database with sequelize, created_at and updated_at are automatically filled and this is with this error:
"name": "SequelizeValidationError",
"errors": [
{
"message": "createdAt cannot be an array or an object",
"type": "string violation",
"path": "createdAt",
"value": "2020-05-28T22:04:45.023Z",
"origin": "CORE",
"instance": {
"id": null,
"placeId": "1",
"userId": 3,
"name": "Alex Santos",
"email": "customer#gmail.com",
"documento": "00000000000",
"phone": "(37)98596-9869",
"updatedAt": "2020-05-28T22:04:45.023Z",
"createdAt": "2020-05-28T22:04:45.023Z"
},
"validatorKey": "not_a_string",
"validatorName": null,
"validatorArgs": []
},
{
"message": "customer.updateAt cannot be null",
"type": "notNull Violation",
"path": "updateAt",
"value": null,
"origin": "CORE",
"instance": {
"id": null,
"placeId": "1",
"userId": 3,
"name": "Alex Santos",
"email": "customer#gmail.com",
"documento": "031.682.546-81",
"phone": "(37)98596-9869",
"updatedAt": "2020-05-28T22:04:45.023Z",
"createdAt": "2020-05-28T22:04:45.023Z"
},
"validatorKey": "is_null",
"validatorName": null,
"validatorArgs": []
}
]
}
Can someone provide any suggestions to help? I think in customer.js create() function is having some sort of miss from my side.
Could there be any other solution?
customer.js
/* jshint indent: 1 */
module.exports = function(sequelize, DataTypes) {
return sequelize.define('customer', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'id'
},
placeId: {
type: DataTypes.INTEGER(11),
allowNull: false,
references: {
model: 'places',
key: 'id'
},
field: 'place_id'
},
userId: {
type: DataTypes.INTEGER(11),
allowNull: false,
references: {
model: 'users',
key: 'id'
},
field: 'user_id'
},
customerId: {
type: DataTypes.INTEGER(11),
allowNull: true,
field: 'customer_id'
},
name: {
type: DataTypes.STRING(100),
allowNull: false,
field: 'name'
},
email: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'email'
},
documento: {
type: DataTypes.STRING(16),
allowNull: false,
defaultValue: '',
field: 'documento'
},
phone: {
type: DataTypes.STRING(12),
allowNull: false,
field: 'phone'
},
createdAt: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'created_at'
},
updateAt: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'update_at'
}
}, {
tableName: 'customer'
});
};
CustomerController.js
const Customers = require('./../models/custumers')
const Sequelize = require('sequelize');
const db = require('../../bin/database');
const Customer = new Customers(db, Sequelize);
exports.create = async(req, res) => {
decodeToken = await jwt.decodeToken(req.headers['x-access-token'])
let userId = decodeToken.id
console.log(new Date())
let { placeId, customerId, name, email, documento, phone } = req.body
Customer.create({
placeId,
userId,
customerId,
name,
email,
documento,
phone
})
.then((Customer) => {
return res.status(200).send({ Customer: Customer })
}).catch(err => {
res.status(423).send(err);
});
}

The error message is telling you what is wrong. You defined the createdAt column as a String but it would appear that you are sending an object (very likely of type Date). The value of type Date is not a String, and so Sequelize is warning you with information like "validatorKey": "not_a_string" and "type": "string violation".
I don't know why you elected to store a timestamp as a String, but part of the fix is to change the column to type Date.
You also mentioned that the column value is filled automatically, but I don't see anywhere where that would take place. Unless you are explicitly setting a default value for the column and then not providing a value when committing the session, these columns will not be automatically filled.
The short answer is, change the column type to DATE and make sure to set a timestamp on the value before committing to the db.

Related

Sequalize relationship betwen same model

I am creating a chat application and trying to create a relationship between User and User through friendship. So far I can create a relationship, but in the end only one user assigned a friend. I'm using Express, sequalize with postgress deployed to heroku. I don't know how to achieve it, any help is appreciated
migration:
`enter code here`await queryInterface.createTable('users', { id: { type: DataTypes.UUID, primaryKey: true, defaultValue: DataTypes.UUIDV4, } }, }); await queryInterface.createTable('friendships', { id: { type: DataTypes.UUID, primaryKey: true, defaultValue: DataTypes.UUIDV4, }, user: { type: DataTypes.UUID, allowNull: false, references: { model: 'users', key: 'id' }, }, friend: { type: DataTypes.UUID, allowNull: false, references: { model: 'users', key: 'id' }, }, status: { type: DataTypes.ENUM('PENDING', 'ACCEPTED', 'DENIED'), allowNull: false, defaultValue: 'PENDING', }, });
friendship model:
Friendship.init(
{
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
},
user: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
friend: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
status: {
type: DataTypes.ENUM('PENDING', 'ACCEPTED', 'DENIED'),
allowNull: false,
defaultValue: 'PENDING',
},
},
{
sequelize,
underscored: true,
timestamps: false,
modelName: 'friendship',
}
);
associations:
User.belongsToMany(User, { as: 'friends', through: Friendship, foreignKey: 'user',
otherKey: 'friend' });
Friendship.belongsTo(User, { as: 'info', foreignKey: 'friend' });
controller:
export const addFriend = async (req: Request, res: Response) => {
try {
const { friendId } = req.body;
const userId = req.decodedToken?.id;
const friend = await User.findByPk(friendId, {
attributes: { exclude: ['passwordHash'] },
include: [{ model: User, as: 'friends' }],
});
if (friend)
await Friendship.create({
user: userId,
friend: friend.id,
status: 'PENDING',
});
return res.status(200).json({ status: 'success' });
} catch (e) {
res.status(500).json({ error: 'The server cannot create the user' });
console.log(e);
}
};
response:
"users": {
"count": 2,
"rows": [
{
"id": "e7c7ce39-953a-45e7-a892-a5f99554382e",
"email": "admin",
"username": "admin",
"name": null,
"surname": null,
"age": null,
"public": true,
"image": null,
"friends": [
{
"id": "13029ad9-7199-47d5-bd1c-7d939b26150e",
"email": "admin2",
"username": "admin",
"passwordHash": "$2b$10$GajlewYeiGvUOOV08YOzLuedV/8.KJNUeHB4WPKlUFxErj91ljfWq",
"name": null,
"surname": null,
"age": null,
"public": true,
"image": null,
"friendship": {
"id": "a78b9336-f5a6-4153-b3e1-e44dbe1cc7a6",
"user": "e7c7ce39-953a-45e7-a892-a5f99554382e",
"friend": "13029ad9-7199-47d5-bd1c-7d939b26150e",
"status": "PENDING"
}
}
]
},
{
"id": "13029ad9-7199-47d5-bd1c-7d939b26150e",
"email": "admin2",
"username": "admin",
"name": null,
"surname": null,
"age": null,
"public": true,
"image": null,
"friends": []
}
Edit:
I made something like this, it's not perfect, but it's good for me
User.belongsToMany(User, { as: 'friends', through: Friendship, foreignKey: 'user' });
User.belongsToMany(User, { as: 'friend', through: Friendship, foreignKey: 'friend' });
Please consider a many to many relationship.
An user can be a friend of many users.
Many users can be friends of one user.
You may found the how-to implement in the official doc: here.
Basically, use belongsToMany in both associations:
Implementation
The main way to do this in Sequelize is as follows:
const Movie = sequelize.define('Movie', { name: DataTypes.STRING });
const Actor = sequelize.define('Actor', { name: DataTypes.STRING });
Movie.belongsToMany(Actor, { through: 'ActorMovies' });
Actor.belongsToMany(Movie, { through: 'ActorMovies' });

Sequelize - Return only relationships

I have a problem, I need to return an array just from my flows relationship. How can I get an array with a list of the flows of all companies?
My model and migrations are correct, I just don't know how to make the query return only the flows.
Company Model
module.exports = (sequelize) => {
const company = sequelize.define('company', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4
},
name: {
type: DataTypes.STRING,
allowNull: false
}
})
company.hasMany(sequelize.models.flow, {foreignKey: 'company_id', as: 'flows'})
}
Flow model
module.exports = (sequelize) => {
const flow = sequelize.define('flow', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
company_id: {
allowNull: false,
type: DataTypes.INTEGER
},
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4
},
name: {
type: DataTypes.STRING,
allowNull: false
},
description: {
type: DataTypes.TEXT
}
})
flow.belongsTo(sequelize.models.company, {foreignKey: 'company_id', as: 'company'})
}
Query
const companies = await ORM.models.company
.findAll({
include: [{
model: ORM.models.flow,
as: 'flows'
}]
})
This query is returning like this:
[
{
"id": 1,
"uuid": "f0c1a5e1-c54c-4083-8284-5a9b272e8ba1",
"name": "Company 1",
"created_at": "2021-02-11T05:47:55.830Z",
"updated_at": "2021-02-11T05:47:55.830Z",
"flows": [
{
"id": 1,
"company_id": 1,
"uuid": "768262d2-88b7-4e0f-81e8-30d7253aae65",
"name": "Flow 1",
"description": null,
"created_at": "2021-02-11T05:48:10.211Z",
"updated_at": "2021-02-11T05:48:10.211Z",
"companyId": 1
}
]
},
{
"id": 2,
"uuid": "3dea2541-a505-4f0c-a356-f1a2d449d050",
"name": "Company 1",
"created_at": "2021-02-11T05:48:11.872Z",
"updated_at": "2021-02-11T05:48:11.872Z",
"flows": [
{
"id": 2,
"company_id": 2,
"uuid": "3e66e8e6-3754-41e5-93ca-6e8ed49e2025",
"name": "Flow 2",
"description": null,
"created_at": "2021-02-11T05:48:20.743Z",
"updated_at": "2021-02-11T05:48:20.743Z",
"companyId": 2
}
]
}
]
I need to return like this:
[
{
"id":1,
"company_id":1,
"uuid":"768262d2-88b7-4e0f-81e8-30d7253aae65",
"name":"Flow 1",
"description":null,
"created_at":"2021-02-11T05:48:10.211Z",
"updated_at":"2021-02-11T05:48:10.211Z",
"companyId":1
},
{
"id":2,
"company_id":2,
"uuid":"3e66e8e6-3754-41e5-93ca-6e8ed49e2025",
"name":"Flow 2",
"description":null,
"created_at":"2021-02-11T05:48:20.743Z",
"updated_at":"2021-02-11T05:48:20.743Z",
"companyId":2
}
]
If you just want the flows related data, why to fetch company related data with flows in it? Perhaps, you could only fetch flows data.
const flows = await ORM.models.flow
.findAll({
where: ....,
..........
});
If anyhow, you still want to show the flows for particular companies without showing any attributes of the company model, just do something like this:
const companies = await ORM.models.company
.findAll({
attributes: [], //empty
include: [{
model: ORM.models.flow,
as: 'flows'
}]
});

sequelize database error with no error message

It's my first time using PostgreSQL and I'm creating a REST API that using sequelize for postgresql, expressjs and nodejs.
I created a user and each user has many parcels. I am now creating a parcel which belongs to a user using userId as reference. I keep getting the database sequelize error and it has no message. It's routine says, 'checkInsertTarget'.
Error message
{
"name": "SequelizeDatabaseError",
"parent": {
"name": "error",
"length": 190,
"severity": "ERROR",
"code": "42703",
"position": "48",
"file": "d:\\pginstaller.auto\\postgres.windows-x64\\src\\backend\\parser\\parse_target.c",
"line": "1033",
"routine": "checkInsertTargets",
"sql": "INSERT INTO \"Parcels\" (\"id\",\"name\",\"delivered\",\"presentLoc\",\"destination\",\"description\",\"createdAt\",\"updatedAt\",\"userId\") VALUES (DEFAULT,'Shoe',false,'Onitsha','ESUT','black shoe, size 34','2018-11-25 15:48:13.100 +00:00','2018-11-25 15:48:13.100 +00:00','3') RETURNING *;"
},
"original": {
"name": "error",
"length": 190,
"severity": "ERROR",
"code": "42703",
"position": "48",
"file": "d:\\pginstaller.auto\\postgres.windows-x64\\src\\backend\\parser\\parse_target.c",
"line": "1033",
"routine": "checkInsertTargets",
"sql": "INSERT INTO \"Parcels\" (\"id\",\"name\",\"delivered\",\"presentLoc\",\"destination\",\"description\",\"createdAt\",\"updatedAt\",\"userId\") VALUES (DEFAULT,'Shoe',false,'Onitsha','ESUT','black shoe, size 34','2018-11-25 15:48:13.100 +00:00','2018-11-25 15:48:13.100 +00:00','3') RETURNING *;"
},
"sql": "INSERT INTO \"Parcels\" (\"id\",\"name\",\"delivered\",\"presentLoc\",\"destination\",\"description\",\"createdAt\",\"updatedAt\",\"userId\") VALUES (DEFAULT,'Shoe',false,'Onitsha','ESUT','black shoe, size 34','2018-11-25 15:48:13.100 +00:00','2018-11-25 15:48:13.100 +00:00','3') RETURNING *;"
}
Parcel migration code
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Parcels', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
delivered: {
type: Sequelize.BOOLEAN
},
presentLoc: {
type: Sequelize.STRING
},
destination: {
type: Sequelize.STRING
},
description: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
},
userId: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
references: {
model: 'Users',
key: 'id',
as: 'userId',
}
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Parcels');
}
};
Parcel model code
'use strict';
module.exports = (sequelize, DataTypes) => {
const Parcel = sequelize.define('Parcel', {
name: {
type: DataTypes.STRING,
allowNull: false
},
delivered: {
type: DataTypes.BOOLEAN,
defaultValue: false
},
presentLoc: {
type: DataTypes.STRING,
allowNull: false
},
destination: {
type: DataTypes.STRING,
allowNull: false
},
description: DataTypes.STRING,
}, {});
Parcel.associate = (models) => {
Parcel.belongsTo(models.User, {
foreignKey: 'userId',
onDelete: 'CASCADE'
})
};
return Parcel;
};
Parcel controller
const Parcel = require('../models').Parcel;
const joiSchema = require('../joischema/parcelSchema');
const validator = require('../joischema/validator');
module.exports = {
create(req, res) {
const data = {
name: req.body.name,
description: req.body.description,
destination: req.body.destination,
presentLoc: req.body.presentLoc,
userId: req.params.userId,
};
const valid = validator.isValid(req, res, joiSchema, data);
if (valid != null){
res.status(500).send(valid);
}else{
return Parcel
.create(data)
.then(parcel => res.status(201).send(parcel))
.catch(error => res.status(400).send(error));
}
}
I checked the database and saw a column that I thought I'd removed. I had to run sequelize db:migrate:undo and then sequelize db:migrate again to incorporate my changes i.e. removing that column.

nodejs sequelize join 2 table using hasmany

I am new in nodejs. I am creating new app using nodejs. i want to join two table city and state using hasmany relations.
Here is my state model state.js
module.exports = function(sequelize, DataTypes) {
return sequelize.define('state', {
name: {
type: DataTypes.STRING(255),
allowNull: true
},
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
createdAt: {
type: DataTypes.DATE,
allowNull: true
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true
}
}, {
tableName: 'state'
});
};
Here is my city model city.js
module.exports = function(sequelize, DataTypes) {
return sequelize.define('city', {
state: {
type: DataTypes.INTEGER(11),
allowNull: true
},
name: {
type: DataTypes.STRING(255),
allowNull: true
},
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
createdAt: {
type: DataTypes.DATE,
allowNull: true
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true
}
}, {
tableName: 'city'
});
};
This is my citycontroller.js
let City = require('../models').city;
let State = require('../models').state;
let message = require('../../config/message');
let Boom = require('boom');
module.exports = {
listCity: async(request,h) =>{
let stateid = request.query.stateid;
try{
let searchQuery = {};
if(stateid) searchQuery.state = stateid;
let listCity = await City.findAll({ where:searchQuery});
if(listCity.length){
let response = {
"statusCode": 200,
"message":message.DATAFOUND,
"result": listCity
};
return h.response(response).code(200);
}else{
return h.response(response).code(204);
}
}catch(err){
return Boom.badRequest(err.message);
}
},
};
Output:
{
"statusCode": 200,
"message": "Data found",
"result": [
{
"state": 1,
"name": "Los Angeles",
"id": 1,
"createdAt": null,
"updatedAt": null
},
{
"state": 1,
"name": "San Francisco",
"id": 2,
"createdAt": null,
"updatedAt": null
},
{
"state": 5,
"name": "Southhampton",
"id": 3,
"createdAt": null,
"updatedAt": null
}
]
}
Now it listing city details only. but i need to join state details also under each city.
If you want to select the data from the state table than define a relation in the state model.
module.exports = function(sequelize, DataTypes) {
const state = sequelize.define('state', {
name: {
type: DataTypes.STRING(255),
allowNull: true
},
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
createdAt: {
type: DataTypes.DATE,
allowNull: true
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true
}
}, {
tableName: 'state'
});
state.associate = function(model){
models.state.hasMany(models.city){
foreignKey: 'state'
}
return state;
}
};
Or if you want to select data from the city table than define a similar hasOne relation in city table.

findAll doesn't get object structure according to Includes Sequelize

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.

Resources