Sequelize set alias attributes name after join - mysql

After a join operation among three models I received a valid result but I would rename the attributes generated by the join operation of the findAll
Query:
const orchards = await db.Area.findAll({
include: [db.AreaCoordinate, db.Crop],
attributes: ['id', 'name']
});
AreaCoordinate Model:
module.exports = function (sequelize, DataTypes) {
var AreaCoordinate = sequelize.define('AreaCoordinate', {
latitude: {
type: DataTypes.STRING(45),
allowNull: true
},
longitude: {
type: DataTypes.STRING(45),
allowNull: true
}
}, {
classMethods: {
associate: function (models) {
AreaCoordinate.belongsTo(models.Area, {foreignKey: 'areaId'});
}
}
});
return AreaCoordinate;
};
Crop Model:
module.exports = function (sequelize, DataTypes) {
var Crop = sequelize.define('Crop', {
name: {
type: DataTypes.STRING(45),
allowNull: true
},
lang: {
type: DataTypes.STRING(45),
allowNull: true
}
}, {
classMethods: {
associate: function (models) {
Crop.hasMany(models.Area, {foreignKey:'cropId'})
}
}
});
return Crop;
};
Area Model:
module.exports = function (sequelize, DataTypes) {
var Area = sequelize.define('Area', {
name: DataTypes.STRING
}, {
classMethods: {
associate: function (models) {
// example on how to add relations
Area.belongsTo(models.Crop, {foreignKey: 'cropId'});
Area.belongsTo(models.Orchard, {as: 'orchard'});
Area.hasMany(models.AreaCoordinate, {foreignKey:'areaId'})
}
}
});
return Area;
};
I would receive from the query a JSON like this:
{
"status": 200,
"status_message": "OK",
"data": {
"orchard": [
{
"name": "pantano",
"coordinates": [
{
"id": 115,
"latitude": "1",
"longitude": "2",
"createdAt": "2017-08-29T12:03:11.000Z",
"updatedAt": "2017-08-29T12:03:11.000Z",
"areaId": 28
},
{
"id": 116,
"latitude": "1",
"longitude": "2",
"createdAt": "2017-08-29T12:03:11.000Z",
"updatedAt": "2017-08-29T12:03:11.000Z",
"areaId": 28
}
],
"cropId": 10
}
]
}
}
But what I receive is (look AreaCoordinates and Crop):
{
"status": 200,
"status_message": "OK",
"data": {
"orchard": [
{
"name": "pantano",
"AreaCoordinates": [
{
"id": 115,
"latitude": "1",
"longitude": "2",
"createdAt": "2017-08-29T12:03:11.000Z",
"updatedAt": "2017-08-29T12:03:11.000Z",
"areaId": 28
},
{
"id": 116,
"latitude": "1",
"longitude": "2",
"createdAt": "2017-08-29T12:03:11.000Z",
"updatedAt": "2017-08-29T12:03:11.000Z",
"areaId": 28
}
],
"Crop": 10
}
]
}
}
I tried to set some alias for AreaCoordinates and Crop but I couldn't find a solution. Thank you in advance for your support.

Write query like this:
const result = await Table.findAll({
attributes: ['id', ['foo', 'bar']] //id, foo AS bar
});

By default in Sequelize association, it will set the attribute name as the related model name. For your case, the related model named AreaCoordinates, so the attribute name in return will be AreaCoordinates. You should use as. Modify yours and Try this:
###findAll Query:
const orchards = await db.Area.findAll({
include: [
{
model: db.AreaCoordinate,
as: 'coordinates'
}, {
model: db.Crop,
as: 'cropId',
attributes: ['id']
}],
attributes: ['id', 'name']
});
###Area Model
module.exports = function (sequelize, DataTypes) {
var Area = sequelize.define('Area', {
name: DataTypes.STRING
}, {
classMethods: {
associate: function (models) {
// example on how to add relations
Area.belongsTo(models.Crop, {
foreignKey: 'cropId',
as: 'cropId'
});
Area.belongsTo(models.Orchard, {as: 'orchard'});
Area.hasMany(models.AreaCoordinate, {
foreignKey:'areaId',
as: 'coordinates'
})
}
}
});
return Area;
};

Related

One to many relationship in sequelize with MYSQL

I have two tables:
const attr = {
name: {
type: DataTypes.STRING,
},
};
const Tags = createModel('Tags', attr, {});
and:
const attr = {
tagId: {
type: DataTypes.INTEGER,
references: { model: 'Tags', key: 'id' },
}
}
const Client = createModel('Client', attr, {})
Client.belongsTo(Tag, { foreignKey: 'tagId', as: 'tags' });
and my query is this:
const clientCount = await Client.findAll({
include: [ { model: Tags, as: 'tags' } ],
attributes: { exclude: 'tagId' }
});
and this is my response:
{
"id": 1,
"createdAt": "2020-01-20T00:00:00.000Z",
"updatedAt": "2020-01-22T00:00:00.000Z",
"tags": {
"id": 1,
"name": "New tag",
"createdAt": "2020-01-20T00:00:00.000Z",
"updatedAt": "2020-01-20T00:00:00.000Z"
}
}
but I want my tags to be an array, so I guest I have to define a one to many association, but everything I tried so far failed.
What I want is tags to be an array, where I can add multiple tag objects:
{
"id": 1,
"createdAt": "2020-01-20T00:00:00.000Z",
"updatedAt": "2020-01-22T00:00:00.000Z",
"tags": [
{
"id": 1,
"name": "New tag",
"createdAt": "2020-01-20T00:00:00.000Z",
"updatedAt": "2020-01-20T00:00:00.000Z"
}
]
}
Method1
We need new model as Client_Tag
const attr = {
clientId: {
type: DataTypes.INTEGER,
},
tagId: {
type: DataTypes.INTEGER,
},
};
const Client_Tag = createModel('Client_Tag', attr, {});
Client.belongsToMany(Tag, {
foreignKey: 'clientId',
otherKey: 'tagId',
through: models.Client_Tag,
as: 'tags'
});
const clientCount = await Client.findAll({
include: [ { model: Tags, as: 'tags' } ],
attributes: { exclude: 'tagId' }
});
Method2
const attr = {
name: {
type: DataTypes.STRING,
},
clientId: { // need clientId in tag model, and remove 'tagId' from client model
type: DataTypes.INTEGER,
}
};
const Tags = createModel('Tags', attr, {});
Client.belongsToMany(Tag, { foreignKey: 'tagId', as: 'tags' });

Sequelize populate joined table attributes

I have a few tables and I want to do some includes on a joined table, but I can't seem to figure it out. Here are my models:
/* Staff model */
const model = {
fisrName: {
type: DataTypes.INTEGER,
references: { model: 'Roles', key: 'id' },
},
lastName: {
type: DataTypes.INTEGER,
references: { model: 'Profiles', key: 'id' },
}
};
const Staff = createModel('Staff', model, { paranoid: true });
export default Staff
/* Service model */
const model = {
name: {
type: DataTypes.STRING,
},
category: {
type: DataTypes.STRING,
},
description: {
type: DataTypes.STRING,
}
};
const Service = createModel('Service', model, {});
export default Service;
/* Appointment model */
const model = {
endDate: {
type: DataTypes.DATE,
},
startDate: {
type: DataTypes.DATE,
},
day: {
type: DataTypes.DATE,
},
};
const Appointment = createModel('Appointment', model, {})
Appointment.belongsToMany(Service, { through: 'Products', as: 'products' });
export default Appointment;
/* Products model */
const model = {
serviceId: {
type: DataTypes.INTEGER,
},
appointmentId: {
type: DataTypes.INTEGER,
},
staffId: {
type: DataTypes.INTEGER,
references: { model: 'Staff', key: 'id' },
}
};
const Product = createModel('Product', model, {});
Product.belongsTo(Staff, { foreignKey: 'staffId', as: 'staff' });
export default Product;
This is my appointment query, where I include the services array, and on this services array, I have a Products object, and in this object I have a staffId that I want to populate, and I'm not sure how. I have tried different ways, but nothing worked.
const appointment = await Appointment.findByPk(req.params.id, {
include: [
{
model: Service,
as: 'services',
through: { attributes: { include: ['id', 'staffId', 'serviceId', 'appointmentId'], exclude: ['createdAt', 'updatedAt', 'AppointmentId', 'ServiceId'] },
},
],
});
And this is my response:
{
"startDate": "date",
"endDate": "date",
"day": "date",
"services": [{
"id": 1,
"name": "Service name",
"category": "service category",
"description": "service description",
"Products": {
"id": 1,
"staffId": 2,
"serviceId": 1,
"appointmentId": 1
}
}]
}
What I want is to do is to populate the staffId from Products with the model from the collection, something like this:
{
"startDate": "date",
"endDate": "date",
"day": "date",
"services": [{
"id": 1,
"name": "Service name",
"category": "service category",
"description": "service description",
"Products": {
"id": 1,
"staffId": {
"firstName": "First Name",
"lastName": "Last Name"
},
"serviceId": 1,
"appointmentId": 1
}
}]
}
const appointment = await Appointment.findByPk(req.params.id, {
include: [
{
model: Service,
as: 'services',
through: {
attributes: { include: ['id', 'staffId', 'serviceId', 'appointmentId'], exclude: ['createdAt', 'updatedAt', 'AppointmentId', 'ServiceId'] },
},
include: [{
as: 'Products', model: Product,
include: 'staff'
}]
}
]
});

How to get user information instead of just ID sequelize?

I am using sequelize with mysql,
I have 3 models
posts
Comments
users
posts model
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define('Post', {
title: DataTypes.STRING,
content: DataTypes.TEXT,
userId: DataTypes.INTEGER
}, {});
Post.associate = function(models) {
// associations can be defined here
Post.hasMany(models.Comment, {
foreignKey: 'postId',
as: 'comments',
onDelete: 'CASCADE',
})
Post.belongsTo(models.User, {
foreignKey: 'userId',
as: 'author',
onDelete: 'CASCADE',
})
};
return Post;
};
comments model
const user = require("./user");
module.exports = (sequelize, DataTypes) => {
const Comment = sequelize.define(
"Comment",
{
postId: DataTypes.INTEGER,
comment: DataTypes.TEXT,
userId: DataTypes.INTEGER,
},
{}
);
Comment.associate = function (models) {
// associations can be defined here
Comment.belongsTo(
models.User,
{
foreignKey: "userId",
as: "author",
me: "name",
},
{ name: user.name }
);
Comment.belongsTo(models.Post, {
foreignKey: "postId",
as: "post",
});
};
return Comment;
};
users model
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define(
"User",
{
name: DataTypes.STRING,
email: DataTypes.STRING,
},
{}
);
User.associate = function (models) {
// associations can be defined here
User.hasMany(models.Post, {
foreignKey: "userId",
as: "posts",
onDelete: "CASCADE",
});
User.hasMany(models.Comment, {
foreignKey: "userId",
as: "comments",
onDelete: "CASCADE",
});
};
return User;
};
and following is my response i am getting when i execute the following query
const getAllPosts = async (req, res) => {
try {
const posts = await models.Post.findAll({
include: [
{
model: models.Comment,
as: "comments"
},
{
model: models.User,
as: "author"
}
]
});
return res.status(200).json({ posts });
} catch (error) {
return res.status(500).send(error.message);
}
};
RESPONSE
"posts": [
{
"id": 1,
"title": "1st post ever on this server",
"content": "This is the content of the first post published on this type or architecture",
"userId": 1,
"createdAt": "2021-01-31T10:00:45.000Z",
"updatedAt": "2021-01-31T10:00:45.000Z",
"comments": [
{
"id": 1,
"postId": 1,
"comment": "this is the comment on first post",
"userId": 1, // Also need a key val pair of username and his email ID just instead of UserID
"createdAt": null,
"updatedAt": null
},
{
"id": 2,
"postId": 1,
"comment": "comment second",
"userId": 1,
"createdAt": "2021-01-31T15:34:27.000Z",
"updatedAt": "2021-01-31T15:34:27.000Z"
}
],
"author": {
"id": 1,
"name": "test user",
"email": "testuser#gmail.com",
"createdAt": null,
"updatedAt": null
}
}
]
}
I need the user name of commented user name and email for which i have fields in the table
but i am just getting user ID
how can i go about it,
I am very much new in sequelize, I tried but i am getting get same hasMany and benlongsTo results.
From what I see you doing, you need to run a nested include when getting the comment.
Try this modified code.
const getAllPosts = async (req, res) => {
try {
const posts = await models.Post.findAll({
include: [
{
model: models.Comment,
as: "comments",
include: [
{
model: models.User,
as: "author"
}
]
},
{
model: models.User,
as: "author"
}
]
});
return res.status(200).json({ posts });
} catch (error) {
return res.status(500).send(error.message);
}
};

How would you handle two way relations in relational-pouch?

Is this schema valid in relational-pouch (especially the relations between obj and objList):
let schema = [
{
singular: 'obj', plural: 'objs', relations: {
'objList': { belongsTo: 'objList' },
'attributesEditable': { belongsTo: 'attributesEditable' },
'attributesViewable': { belongsTo: 'attributesViewable' },
},
},
{
singular: 'objList', plural: 'objLists', relations: {
'objs': { hasMany: 'obj' },
'obj': { belongsTo: 'obj' },
},
},
{
singular: 'attributesEditable', plural: 'attributesEditables', relations: {
'obj': { belongsTo: 'obj' },
},
},
{
singular: 'attributesViewable', plural: 'attributesViewables', relations: {
'obj': { belongsTo: 'obj' },
},
},
];
What I want:
My App starts with an entry point which is an obj and this has one objList with many obj in it and so on.
You have one realtion between objList and obj, and should declare it in both parts. But in objList declared two relations. Try this code:
[...]
{
singular: 'obj', plural: 'objs', relations: {
'objList': { belongsTo: 'objList' },
'attributesEditable': { belongsTo: 'attributesEditable' },
'attributesViewable': { belongsTo: 'attributesViewable' },
},
},
{
singular: 'objList', plural: 'objLists', relations: {
'objs': { hasMany: 'obj' }
},
[...]

How to perform join in sails JS

I have documents of the form
challenge:
{
"name": "challenge by abdul",
"created_user_id": "1",
"game_id": "123",
"platform_id": "9857",
"amount": 30
}
game:
{
"_id": "auto_generated",
"name": "NFS",
"version": "3",
}
platform:
{
"_id": "auto_generated",
"name": "ps2",
"version": "sami"
}
I want to perform join query in sails and want result in below format
{
"name": "challenge by abdul",
"created_user_id": "1",
"game_id": "123",
"game_name":"NFS",
"platform_name": "ps2",
"platform_id": "9857",
"amount": 30
}
There is no join in Sails but populate. So you need make associations between models and populate them. Example:
// api/models/Platform.js
module.exports = {
attributes: {
name: {
type: 'string'
},
version: {
type: 'string'
},
game: {
model: 'Game',
via: 'platform'
}
}
};
// api/models/Game.js
module.exports = {
attributes: {
name: {
type: 'string'
},
version: {
type: 'string'
},
platform: {
model: 'Platform',
via: 'game'
}
}
};
You can write following code then:
// api/controllers/AnyController.js
module.exports = {
index: function(req, res) {
Game
.findOne({name: 'MY_GAME'})
.populate('platform')
.then(function(game) {
console.log(game); // Game model
console.log(game.platform); // Platform model
return game;
})
.then(res.ok)
.catch(res.negotiate);
}
};