Why sequelize returns only one result? - node.js

i got some problems while writing code, here is some information:
Models:
'use strict';
module.exports = (sequelize, DataTypes) => {
const news = sequelize.define('news', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
title: DataTypes.STRING,
slug: {
type: DataTypes.STRING(64),
unique: true
},
body: DataTypes.STRING,
postedBy: DataTypes.INTEGER
}, {});
news.associate = function(models) {
models.news.hasMany(models.news_ratings, {
as: 'rate',
foreignKey: models.news_ratings.newsId
})
};
return news;
};
///////////////
'use strict';
module.exports = (sequelize, DataTypes) => {
const news_rating = sequelize.define('news_ratings', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
user: DataTypes.INTEGER,
rating: DataTypes.INTEGER,
newsId: DataTypes.INTEGER
}, {});
news_rating.associate = function(models) {
models.news_ratings.belongsTo(models.news, {
foreignKey: models.news.id
})
};
return news_rating;
};
Controller:
router.get('/news/:from/:count', (req, res, next) => {
if (Number.isInteger(Number(req.params.from)) && Number.isInteger(Number(req.params.count))) {
models.news.findAll({
offset: Number(req.params.from),
limit: Number(req.params.count),
include: [{
as: 'rate',
model: models.news_ratings,
attributes: [
[sequelize.fn('AVG', sequelize.col('rating')), 'rate']
]
}]
})
.then(response => {
console.log(response)
res.json(response)
})
.catch(err => {
console.error(err)
res.status(500).end()
})
} else next()
})
This code returns this result (then fetching /news/0/1):
[{
"id": 1,
"title": "First new",
"slug": "demo:first_new",
"body": "New 1. This is demo ^=^",
"postedBy": 0,
"createdAt": "2020-07-22T13:53:48.000Z",
"updatedAt": "2020-07-22T13:53:48.000Z",
"rate": [
{
"rate": "-0.3333"
}
]
}]
But I have 5 news in my database!
...And then I fetch /news/0/5, i got this:
[
{
"id": 1,
"title": "First new",
"slug": "demo:first_new",
"body": "New 1. This is demo ^=^",
"postedBy": 0,
"createdAt": "2020-07-22T13:53:48.000Z",
"updatedAt": "2020-07-22T13:53:48.000Z",
"rate": [
{
"rate": "0.0000"
}
]
}
]
Look, rate is invalid! It should be -0.3333!
Can someone explain me, why this happen and how to resolve this issue?

Related

using sequilize reference with include model for GraphQL

Good afternoon,
Im using sequilize with graphQL, I have three models
const Company= db.define('Company',{
name: {
type: DataTypes.STRING
},
icon: {
type: DataTypes.STRING
}
});
Empresa.hasMany(Producto, {as: 'products', foreignKey: 'CompanyId'});
const Product = db.define('Product',{
name: {
type: DataTypes.STRING
},
price: {
type: DataTypes.INTEGER
},
icon: {
type: DataTypes.STRING
}
});
Product.belongsTo(Company, {as: 'company', foreignKey: 'CompanyId'});
Producto.hasMany(Off, {as: 'offs', foreignKey: 'ProductID'});
const Off= db.define('Off',{
day: {
type: DataTypes.STRING
},
off: {
type: DataTypes.INTEGER
},
description: {
type: DataTypes.STRING
},
});
Off.belongsTo(Product, {as: 'product', foreignKey: 'ProductID'});
getCompany: async () => {
const companies = await Company.findAll({model:Producto, as: 'productos'}]});
return companies ;
},
its working good, I can get the name of the company and their productos
getProducto: async () => {
const products = await Producto.findAll({include: [{model:Company, as: 'company'},
{model:Off, as: 'off'}]});
return products;
},
its working good as well, I can get products and their off, nevertheless when I want
query GetCompanies {
getCompanies {
name
products {
name
off{
off
description
}
}
}
}
I can get the products, but I see a null the off, its like I can go two levels down or up, somebody know, thanks
graphQL return
{
"data": {
"GetCompanies": [
{
"name": "Exito",
"products": [
{
"name": "pescado robalo",
"off": null
},
{
"name": "carne milanesa",
"off": null
}
]
},
{
"name": "Macro",
"products": [
{
"name": "ponymalta",
"off": null
}
]
}
]
}
}
I did it with
Company.findAll({
include: [{
model: Product,
as: 'products',
include:[{ model:Off, as: 'offs' }]
}]
});

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' });

findAll sequelize with model returning odd values

Solved thanks to : https://stackoverflow.com/a/64702949/14585149
I am looking to list all transactions I have on a mysql database with the associated users.
I have 2 tables / models : Transaction & User
Transaction :
module.exports = function(sequelize, DataTypes) {
return sequelize.define('transactions', {
transaction_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true
},
user_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
references: {
model: 'users',
key: 'user_id'
}
},
account_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
references: {
model: 'accounts',
key: 'account_id'
}
},
}, { tableName: 'transactions' }); };
User :
module.exports = function(sequelize, DataTypes) {
return sequelize.define('users', {
user_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'recipients',
key: 'created_by'
}
},
contact_id: {
type: DataTypes.INTEGER(11),
allowNull: true,
references: {
model: 'contacts',
key: 'contact_id'
}
}, }, {
tableName: 'users',
timestamps: false
});
};
I have made the associations :
Transaction.hasOne(User, {foreignKey:'user_id'});
User.belongsTo(Transaction, {foreignKey:'user_id'});
and my code is :
api.get('/trx', async (req, res) => {
Transaction.findAll({
attributes: ['transaction_id','user_id','account_id'],
include: [{
model: User,
attributes: ['user_id']}]
})
.then(intrx => res.json(intrx))
.catch(res.catch_error)
});
the result :
[
{
"transaction_id": 1,
"user_id": 4,
"account_id": 1,
"user": {
"user_id": 1
}
},
{
"transaction_id": 2,
"user_id": 4,
"account_id": 75,
"user": {
"user_id": 2
}
}
]
why the values of user_id are different ?
I am expecting the user_id = 4 instead of 1 in my first result and user_id = 4 in my second result.
what I am doing wrong ?
You should reverse your associations like this:
Transaction.belongsTo(User, {foreignKey:'user_id'});
User.hasOne(Transaction, {foreignKey:'user_id'});
because Transaction has link to User i.e. belongs to it.

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.

Sequelize set associated value

I have two models, Employees and Offices. Every Employee belongs to one Office, and an Office has many Employees.
I am having difficulty figuring out how to update an Employee's office using Sequelize.
The Employee model is as follows:
let Employee = sequelize.define("Employee", {
id: {
field: 'id',
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
autoIncrement: false
},
name: {
field: 'name',
type: DataTypes.STRING(255),
allowNull: false
}
}, {
freezeTableName: true,
timestamps: false,
deletedAt: false
})
Employee.associate = models => {
Employee.belongsTo(models.Office, {
foreignKey: 'id'
})
}
The Office model is as follows:
let Office = sequelize.define("Office", {
id: {
field: 'id',
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
field: 'name',
type: DataTypes.STRING(255),
allowNull: false
}
}, {
freezeTableName: true,
tableName: 'Lkup_Office',
timestamps: false,
deletedAt: false
})
Office.associate = models => {
Office.hasMany( models.Employee, {
foreignKey: 'id'
})
}
In the database I have the following Employee:
{
"id": "2",
"name" : "John",
"office": {
"id": 2,
"name" : "Seattle"
}
}
... and the following Offices:
[
{
"id": 1,
"name" : "Chicago"
},
{
"id": 2,
"name" : "Seattle"
}
]
I want to change the ID of Employee(1)'s office from 2 ('Seattle') to 1 ('Chicago'); the problem is that with the following query
// PUT /2/office/1
router.put('/:employeeId/office/:officeId', (req, res) => {
models.Employee.findOne({
where:{id:req.params.employeeId},
include:[{model:models.Office}]
}).then( employee => {
models.Office.findOne({
where:{id:req.params.officeId},
include:[{model:models.Employee}]
}).then( office => {
employee.setOffice( office ).then( result => {
res.send( result )
})
})
})
})
... my Employee's office is not updated:
{
"id": "2",
"name" : "John"
"office": {
"id": 2
"name" : "Seattle"
}
}
It doesn't, in fact, do anything at all: no errors, the DB isn't changed. I have a suspicion that there's something I'm not doing correctly, but Sequelize isn't throwing any errors.
router.put('/:employeeId/office/:officeId', (req, res) => {
/*In this first part, I just separated the two queries into two
separate variables*/
let employeeInfo = models.Employee.findOne({
where: {
id: req.params.employeeId
},
include: [{
model: models.Office
}]
});
let officeInfo = models.Office.findOne({
where: {
id: req.params.officeId
},
include: [{
model: models.Employee
}]
});
/*In this next part, we have to use Promise.all, which comes with
bluebird, which is already a part of Sequelize.js. How this next
part is executed will depend on how you have your Sequelize.js code
structured in your application. This may require some trial and error*/
models.sequelize.Promise.all([employeeInfo, officeInfo]).then(([Employee, Office])=> {
return Employee.setOffice(Office);
}).catch(err => {
console.log(err);
});
});

Resources