Convert order by additional operator to sequelize - mysql

I want to convert query MySQL into sequelize, but i don't know
SELECT * FROM `RewardEntries`
ORDER BY `RewardEntries`.`happinessPoint` + `RewardEntries`.`moneyPoint` + `RewardEntries`.`healthyPoint` DESC
Please help me
thanks

There might be a more elegant way to do this. I've tested this with PostgreSQL, although the same would probably work for MySQL, too.
let rewards = await RewardEntry.findAll({
order: [
[ sequelize.literal('happinesspoint + moneypoint + healthypoint'), 'DESC' ]
]
})
Here's a complete sample. The name of the table in the database and all of its columns are all lowercase. That's why the query has just lowercase in it.
let {
Sequelize,
DataTypes,
} = require('sequelize')
async function run () {
let sequelize = new Sequelize('mydb', 'username', 'password', {
host: 'localhost',
port: 5432,
dialect: 'postgres',
logging: console.log
})
let RewardEntry = sequelize.define('RewardEntry', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
HappinessPoint: {
type: DataTypes.INTEGER,
field: 'happinesspoint'
},
MoneyPoint: {
type: DataTypes.INTEGER,
field: 'moneypoint'
},
HealthyPoint: {
type: DataTypes.INTEGER,
field: 'healthypoint'
}
},
{
tableName: 'rewardentries',
timestamps: false
})
let rewards = await RewardEntry.findAll({
order: [
[ sequelize.literal('happinesspoint + moneypoint + healthypoint'), 'DESC' ]
]
})
console.log(JSON.stringify(rewards, null, 2))
await sequelize.close()
}
run()

Related

Graphql using Sequelize + mysql: Database Variable always empty

I have gone through many different solutions to overcome this problem. But nothing seems to be working.
My Files:
database.js
const {Sequelize} = require("sequelize");
var db = {}
const sequelize = new Sequelize('ETconnect', 'root', 'D5kIzmJB', {
host: '10.10.10.11',
port: '3306',
dialect: 'mysql',
define: {
freezeTableName: true,
},
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000,
},
// <http://docs.sequelizejs.com/manual/tutorial/querying.html#operators>
operatorsAliases: false,
})
let models = [
require('./models/users.js'),
]
// Initialize models
models.forEach(model => {
const seqModel = model(sequelize, Sequelize)
db[seqModel.name] = seqModel
})
// Apply associations
Object.keys(db).forEach(key => {
if ('associate' in db[key]) {
db[key].associate(db)
}
})
db.sequelize = sequelize
db.Sequelize = Sequelize
exports.db;
models/users.js
const {Sequelize} = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('users', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(50),
allowNull: false,
unique: "email"
},
password: {
type: DataTypes.STRING(255),
allowNull: false
},
profileimage: {
type: DataTypes.STRING(45),
allowNull: true
}
}, {
sequelize,
tableName: 'users',
timestamps: false,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [
{ name: "id" },
]
},
{
name: "email",
unique: true,
using: "BTREE",
fields: [
{ name: "email" },
]
},
]
});
};
models/init-models.js
var DataTypes = require("sequelize").DataTypes;
var _users = require("./users");
function initModels(sequelize) {
var users = _users(sequelize, DataTypes);
return {
users,
};
}
module.exports = initModels;
module.exports.initModels = initModels;
module.exports.default = initModels;
Graphql/users.js
const {gql} = require("apollo-server-express");
const db = require("../database");
//import { gql } from 'apollo-server-express'
//import * as db from '../database'
exports.typeDefs = gql`
extend type Query {
users: [User]
user(id: ID!): User
}
type User {
id: ID!
name: String
email: String
}
`
exports.resolvers = {
Query: {
users: async () => console.log(db),
user: async (obj, args, context, info) =>
db.users.findByPk(args.id),
},
}
Everytime I use the users query in the Apollo test environment I get a log which says that the Database variable is empty.
Output: {}
Can anybody tell me what I did wrong? Does it not connect to the Database? Because we have a similar application that does perfectly fine.
I would really appreciate the help.

How to write object id reference of mongoose using Sequelize for MySql in Node.js

I am trying to write the category model for MySQL using Sequelize taking reference from this code of mongoose model in node(shared below) . I have gone through some articles but going through some confusion. Please help.
const mongoose = require("mongoose");
const categorySchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
trim: true,
},
createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
},
);
module.exports = mongoose.model("Category", categorySchema);
Here I've tried my code in using Sequelize for MySql but got stuck in createdBy block. Need Help!!!
module.exports = (sequelize, Sequelize) => {
const Category = sequelize.define("categories", {
name:{
type: Sequelize.STRING,
required: true,
trim: true,
},
createdBy:{
}
});
return Category;
};
The createdBy value from Mongo will be an ObjectID, which you can save as a string in MySQL, so use a DataTypes.STRING type in the definition, then set it on insert/update/etc from your Mongo lookup. The Sequelize variable in your example should be DataTypes as well.
module.exports = (sequelize, DataTypes) => {
const Category = sequelize.define('categories', {
name: {
type: DataTypes.STRING,
required: true,
trim: true,
},
createdBy: {
type: DataTypes.STRING,
// any other settings
},
});
return Category;
};
// get the value from mongoose
const createdBy = ...;
// set it on the create for your model to insert.
await Category.create({
name: 'Some Name',
createdBy,
});

Sequelize model.create is not a function

I'm new to sequelize and trying to set it up for my new project. I checked some answers on this, but couldnt get past my error. Can someone point out how to fix this.
models/index.js
// Database service
// Connects to the database
const { Sequelize } = require('sequelize');
const path = require('path');
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
host: process.env.DB_HOST,
dialect: 'mysql',
logging: process.env.QUERY_LOGGING == "true" ? console.log : false,
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000
}
});
module.exports = sequelize
models/users.js
const sequelize = require("./index")
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('Users', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
},
profileURL: {
type: DataTypes.STRING
},
emailId: {
type: DataTypes.STRING,
allowNull: false
},
passwordHash: {
type: DataTypes.STRING,
allowNull: false
},
street: {
type: DataTypes.STRING
},
city: {
type: DataTypes.STRING,
allowNull: false
},
phone: {
type: DataTypes.STRING
},
newsletter: {
type: DataTypes.STRING
},
visibility: {
type: DataTypes.BOOLEAN,
defaultValue: true
},
},{
});
return User;
};
And finally, I'm importing the User model in my service file like below:
const User = require("../models/users")
const createUser = async(req) => {
const {firstName, lastName, profileURL, emailId, passwordHash, street, city, phone, newsletter, visibility} = req.body
const user = await User.create({
firstName,
lastName,
profileURL,
emailId,
passwordHash,
street,
city,
phone,
newsletter,
visibility
})
console.log("new user==>>", user)
return
}
module.exports = { createUser }
However, I get the following error.
TypeError: User.create is not a function
Can someone point out what I could be doing wrong? I realize it could be something minor.
Thank you
You export a function that registers the User model and not the model itself. So you just need to call it passing sequelize instance and DataTypes somewhere like database.js where you will register all models and their associations or directly in models/index.js:
const UserModelConstructor = require("../models/users")
const { DataTypes } = require("sequelize");
...
const UserModel = UserModelConstructor(sequelize, DataTypes);
module.exports = {
sequelize,
User: UserModel
}
You can look at how to register multiple models and association in my other answer here
Please don't forget to remove this line
const sequelize = require("./index")
from models/users.js

Is it possible for Sequelize to include a table from another database in the same query?

I've got a two MySQL Schemas both with a table called User as I want to have a SSO application with multiple microservices. I can't seem to get Sequelize to generate the correct SQL for my needs.
I've tried adding the 'schema' attribute to my model definitions in Sequelize, but it tries to use 'schema_name.schema_name.table_name' instead of 'schema_name.table_name'. I'm unsure whether the schema attribute works for MySQL.
SuperUser.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define(
'User',
{
id: {
primaryKey: true,
type: DataTypes.UUID,
allowNull: false,
},
username: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
company: DataTypes.STRING,
},
{
// tried to add schema: super_schema
underscored: true,
timestamps: true,
paranoid: true,
},
);
User.associate = function(models) {};
return User;
};
SubUser.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define(
'User',
{
id: {
primaryKey: true,
type: DataTypes.UUID,
allowNull: false,
},
role: {
type: VARCHAR(45),
allowNull: false,
},
},
{
underscored: true,
timestamps: true,
paranoid: true,
},
);
User.associate = function(models) {
const { super } = models;
User.belongsTo(super.models.User, { as: 'Super', foreignKey: 'id' });
};
return User;
};
My query is
const user = await db.sub.User.findOne({
include: [
{
model: db.super.User,
as: 'Super',
where: {
username: 'someUsername',
},
},
],
});
I believe the problem lies in how I'm creating the Sequelize instances, I'm creating an instance for each schema connection. So Sequelize doesn't know that db.super.User is different from db.sub.User when written in Javascript.
The problem lies in the INNER JOIN it generates.
It generates
INNER JOIN `users` AS `Super` ON `User`.`id` = `Super`.`id`
I'd like it to generate
INNER JOIN `Super`.`users` AS `Super` ON `User`.`id` = `Super`.`id`

Unable to run a join query using sequelize

I need to run a join query using sequelize and I have been reading the documentation at sequelize doc. But as I run the following snippet, I get an error.
let channelUsersM = UserModel.get(); // Table name: channel_users
let channelM = ChannelModel.get(); // Table name: channel
channelUsersM.belongsTo(channelM, {as: 'channel',foreign_key: 'channel_id',targetKey:'id'});
channelM.hasMany(channelUsersM,{foreign_key: 'channel_id'});
channelUsersM.findAll({
attributes: ['username'],
where: {
usertype: this.userType,
channel: {
name: channelName
}
},
include: [channelM]
}).then((r) => {
resolve(r);
}).catch((err) => {
reject(err);
});
Error says: channel is not associated to channel_users!
What could be the reason for this? I know how to directly run a SQL query using sequelize, but I do not want to go with it.
For easier understanding here, is the equivalent sql query that I am trying with sequelize:
select cu.username from channel as ch left join
channel_users as cu on ch.id = cu.channel_id
ch.name = 'some-name' and cu.usertype = 'some-type';
Here is the definition of models if required:
For channel_users:
channel_id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
field: 'channel_id'
},
userid: {
type: Sequelize.INTEGER,
field: 'userid'
},
username: {
type: Sequelize.CHAR(255),
field: 'username'
},
password: {
type: Sequelize.TEXT,
field: 'password'
},
usertype: {
type: Sequelize.ENUM('user', 'moderator','speaker','owner'),
field: 'usertype'
}
For channel:
id: {
type: Sequelize.INTEGER,
field: 'id',
autoIncrement: true,
primaryKey: true
},
name: {
type: Sequelize.CHAR(255),
field: 'name'
},
display_name: {
type: Sequelize.TEXT,
field: 'display_name'
},
creatorid: {
type: Sequelize.INTEGER,
field: 'creatorid'
},
password: {
type: Sequelize.TEXT,
field: 'password'
},
createdAt: {
type: Sequelize.DATE,
field: 'createdAt'
},
modifiedAt: {
type: Sequelize.DATE,
field: 'modifiedAt'
}
You have defined an alias in the belongsTo association, so you also need to include the alias in include attribute when querying. Moreover, the channel.name column value should also be included in the include object of the query.
channelUsersM.findAll({
attributes: ['username'],
where: {
usertype: this.userType
},
include: [
{
model: channelM,
as: 'channel',
attributes: [],
where: { name: channelName }
}
]
}).then((r) => {
resolve(r);
}).catch((err) => {
reject(err);
});
The attributes: [] in include is added in order to prevent returning any fields from the channel table (according to you query you want only the username field from channel_users table).