i use Sequelize
what i want search userId from another model
when i add "task_customer_order.userId" i got error but when i remove it only userId it's work but foreign key of userId in Comment model not need it i want in task_customer_order model
my code :
count_comment:async(req,res)=>{
var Sequelize = require('sequelize');
const id = req.params.id;
await Comment.findAll({
attributes: {
include: [[Sequelize.fn("COUNT", Sequelize.col('comment.publish')), "count_Comment"]],
},
include: ['task_customer_order'],
where:[{"publish":1,"task_customer_order.userId":{[Op.like]:id}}],
}).then(data => {
res.send(data)
})
},
error:
UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Unknown column 'comment.task_customer_order.userId' in 'where clause'
output without userId:
{
"id": 1,
"title_body": "1",
"publish": true,
"createdAt": "2021-01-04T17:34:46.000Z",
"updatedAt": "2021-01-04T17:57:52.000Z",
"taskCustomerOrderId": 1,
"userId": 2, <============= i don't need it
"count_Comment": 6,
"task_customer_order": {
"id": 1,
"title_task": "yy",
"description": "",
"endAt": "2021-02-12T21:00:00.000Z",
"duration": "09-02",
"publish": true,
"createdAt": "2021-01-04T17:32:47.000Z",
"updatedAt": "2021-01-04T21:49:15.000Z",
"customerOrderId": 1,
"userId": 1 <==================== i want this
}
}
If you would like to filter by userId in joined task_customer_order - you need to put condition inside include. Try the next:
await Comment.findAll({
attributes: {
include: [[Sequelize.fn("COUNT", Sequelize.col('comment.publish')), "count_Comment"]],
},
include: [{ model: TaskCustomerOrder, where:{userId: {[Op.like]:id}}}],
where:{"publishâ:1},
}).then(data => {
res.send(data)
})
here Code After solving :
count_comment:async(req,res)=>{
var Sequelize = require('sequelize');
const id = req.params.id;
await Comment.findAll({
attributes: {
include: [[Sequelize.fn("COUNT", Sequelize.col('comment.publish')), "count_Comment"]],
},
include: [{ model: TaskCustomerOrder,as:'task_customer_order', where:{'userId': {[Op.like]:id}}}],
where:{publish:1},
}).then(data => {
res.send(data)
})
},
Related
I have a Post, User, Comment section with the following schemas:
postSchema = mongoose.Schema({
post_title,
post_description,
post_timestamp,
post_author:{
type:mongoose.Schema.Types.ObjectId,
ref: "User"
},
post_likes:{
type: [userSchema.schema]
},
post_comments:{
type: [commentSchema.schema]
}
)}
userSchema = mongoose.Schema({
username,
email,
password,
date
})
commentSchema = mongoose.Schema({
comment_description,
comment_timestamp,
comment_author:{
type:mongoose.Schema.Types.ObjectId,
ref: "User",
require:true,
}
})
The format that I want my output is the following:
{
"_id": "638bdf38b2ad86abe32455fd",
"post_title": "This is a test post",
"post_description": "abc...",
"post_timestamp": "2022-12-03T23:41:04.292Z",
"post_author": {
"username": "test10"
},
"post_comments": [
{
"comment_description": "This is my first comment for this new post",
"comment_timestamp": "2022-12-03T23:51:24.306Z",
"comment_author": {
"username": "test10"
}
},
{
"comment_description": "This is my first comment for this new post",
"comment_timestamp": "2022-12-04T10:06:22.091Z",
"comment_author": {
"username": "test11"
}
}
]
}
i.e. for the post_comments I would like the _id and __v removed.
I'm receiving my post documents/objects from my server in the following format:
{
"_id": "638bdf38b2ad86abe32455fd",
"post_title": "This is a test post",
"post_description": "abc...",
"post_timestamp": "2022-12-03T23:41:04.292Z",
"post_author": {
"username": "test10"
},
"post_comments": [
{
"comment_description": "This is my first comment for this new post",
"comment_timestamp": "2022-12-03T23:51:24.306Z",
"comment_author": {
"username": "test10"
},
"_id": "638be126b9fe7d1b4823882c",
"__v": 0
},
{
"comment_description": "This is my first comment for this new post",
"comment_timestamp": "2022-12-04T10:06:22.091Z",
"comment_author": {
"username": "test11"
},
"_id": "638c738ab63be98a89d2cb76",
"__v": 0
}
]
}
This is my code to get the data in my app.js route
const posts = await Post.find({}, {
post_title: 1,
post_description: 1,
post_timestamp: 1
})
.populate({
path: "post_author",
model: "User",
select: "-_id username",
})
.populate({
path: "post_comments",
model: "Comment",
select: "-_id -__v comment_description comment_timestamp", // <-- This doesn't work
populate: {
path: "comment_author",
model: "User",
select: "-_id:0 username"
}
})
My select value doesn't make a difference for the post_comments bit. I could use it as is, but I'd like to understand why it's not working. I'm overlooking something but I'm not sure what it is.
I've tried writing the select in other ways, for example:
.populate({
path: "post_comments",
model: "Comment",
_id: 0,
__v: 0,
// select: "-_id -__v comment_description comment_timestamp",
populate: {
path: "comment_author",
model: "User",
select: "-_id username"
}
})
and nothing I do seems to work
I've also tried the solution in this question: Mongoose select with populate not working but that hasn't worked either.
Doing:
.populate("post_comments", "comment_description")
Gives me the following output:
...
"post_comments": [
{
"comment_description": "This is my first comment for this new post",
"comment_timestamp": "2022-12-03T23:51:24.306Z",
"comment_author": "63697530dbf87061fa4c1665",
"_id": "638be126b9fe7d1b4823882c",
"__v": 0
},
...
I come from this topic:
NodeJS & Sequelize: How can I join 3 models?
I come to you now, because I need someone who can teach me about how to get started on junction models with NodeJS and Sequelize.
What I'm trying to do is, having 2 main models, for example, Employee and Office, a 3rd model called EmployeeOffice enters and connects the 2 main models, including its own field called "employee_chair". When i call a method, for example, Office.findAll, this is what I would get:
{
"id": 1,
"office_name": "Mars"
"office_color": "Red",
"createdAt": "2021-09-30T18:53:38.000Z",
"updatedAt": "2021-09-30T18:53:38.000Z",
"employees": [
{
"id": 1,
"employee_name": "Albert",
"employee_mail": "qalbert443#gmail.com",
"createdAt": "2021-09-30T18:53:45.000Z",
"updatedAt": "2021-09-30T18:53:45.000Z",
"employee_office": {
"createdAt": "2021-09-30T18:53:45.000Z",
"updatedAt": "2021-09-30T18:53:45.000Z"
}
}
]
}
NOW. What I need, is to have the model called instead of the junction table that is automatically created. Because I can join the 3 tables, but the 3rd table has the field "employee_chair", that I mentioned earlier. The desired response would look like this:
{
"id": 1,
"office_name": "Mars"
"office_color": "Red",
"createdAt": "2021-09-30T18:53:38.000Z",
"updatedAt": "2021-09-30T18:53:38.000Z",
"employees": [
{
"id": 1,
"employee_name": "Albert",
"employee_mail": "qalbert443#gmail.com",
"createdAt": "2021-09-30T18:53:45.000Z",
"updatedAt": "2021-09-30T18:53:45.000Z",
"employee_office": {
"employee_chair": 3,
"createdAt": "2021-09-30T18:53:45.000Z",
"updatedAt": "2021-09-30T18:53:45.000Z"
}
}
]
}
How can I do to make (or force) sequelize to make the relations through the model and not through the automatically created table?
Hope you guys can help me, I'm stuck and I don't know where to ask
#cupid22 Here is my index.js, userproject model and the controller function im calling:
index.js:
const dbConfig = require("../config/db.config.js");
const Sequelize = require("sequelize");
const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
host: dbConfig.HOST,
dialect: dbConfig.dialect,
operatorsAliases: false,
pool: {
max: dbConfig.pool.max,
min: dbConfig.pool.min,
acquire: dbConfig.pool.acquire,
idle: dbConfig.pool.idle
}
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.projects = require("./project.model.js")(sequelize, Sequelize);
db.users = require("./user.model.js")(sequelize, Sequelize);
db.projects.belongsToMany(db.users, {
through: "users_projects",
as: "users",
foreignKey: "user_id",
});
db.users.belongsToMany(db.projects, {
through: "users_projects",
as: "projects",
foreignKey: "project_id",
});
module.exports = db;
Controller function:
// Retrieve all Projects from the database.
exports.findAll = (req, res) => {
const title = req.query.title;
var condition = title ? { title: { [Op.like]: `%${title}%` } } : null;
Project.findAll({
include: [
{
model: User,
as: "users",
}]
})
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while retrieving projects."
});
});
};
UserProject Model:
module.exports = (sequelize, Sequelize) => {
const UserProject = sequelize.define('user_project', {
user_id: {
type: Sequelize.INTEGER,
references: {
model: 'user',
key: 'id'
}
},
project_id: {
type: Sequelize.INTEGER,
references: {
model: 'project',
key: 'id'
}
},
user_type: {
type: Sequelize.INTEGER,
}
}, {
timestamps: false,
tableName: 'users_projects'
});
db.users.belongsToMany(db.projects, { through: User_Profile });
db.projects.belongsToMany(db.users, { through: User_Profile });
return UserProject;
};
I have created two associated tables (Account, AccountCLI) using SEQUELIZE in Nodejs. Account table has many association with AccountCLI table. Account table has column(userid, eppusername, username, vendorsparameter, projectid). AccountCLI table has column(phonenumber, userid(ForeignKey)). When a user enter a phonenumber, it will return the corresponding userdata. In my code, it returns all the user data rather than specific user with the phone number. You can find the code below. Please give some suggestion?
The tables entries are shown as:
'use strict';
module.exports = (sequelize, DataTypes) => {
const Account = sequelize.define('Account', {
epprojectname: DataTypes.STRING,
username: DataTypes.STRING,
projectid: DataTypes.STRING,
vendorparameters: DataTypes.STRING,
credentials: DataTypes.STRING
}, {});
Account.associate = function(models) {
Account.hasMany(models.AccountCLI, {
as: 'accountcli',
foreignKey: 'userid'
});
};
return Account;
};
'use strict';
module.exports = (sequelize, DataTypes) => {
const AccountCLI = sequelize.define('AccountCLI', {
phonenumber: DataTypes.STRING,
userid: DataTypes.INTEGER
}, {});
AccountCLI.associate = function(models) {
AccountCLI.belongsTo(models.Account, {
as: "account",
foreignKey: 'userid'
});
};
return AccountCLI;
};
The code (that suppose to retrieve specific user data) retrieving all the user data when entered a phone number value are shown as (This is the code after the suggestions):
// find account with specific number
exports.findSpecificUser = async (req, res) => {
var whereStatement = {};
if(req.body.phonenumber)
whereStatement['$accountcli.phonenumber$'] = {$like: '%' + req.body.phonenumber + '%'};
Account.findAll({ include: { model: AccountCLI, as: "accountcli", where: whereStatement } })
.then((data) => {
res.send(data);
})
.catch((err) => {
res.status(500).send({
message:
err.message || "Some error occurred while retrieving account with the specific phonenumber.",
});
});
};
This is the JSON file which I retrieved using POSTMAN. Here I put (phonenumber, 3334) which suppose to retrieve ("epprojectname": "DFSumitayayabot") userdata, but it retrieves both of the user info.
[
{
"id": 68,
"epprojectname": "DFSumitayayabot",
"username": "Sumit",
"projectid": "ayayabot",
"vendorparameters": "newparameters",
"credentials": "1589956379476-tslint.json",
"createdAt": "2020-05-19T15:23:00.440Z",
"updatedAt": "2020-05-20T06:36:05.903Z",
"accountcli": [
{
"id": 227,
"phonenumber": "33344",
"userid": 68,
"createdAt": "2020-05-20T06:36:05.997Z",
"updatedAt": "2020-05-20T06:36:05.997Z"
},
{
"id": 228,
"phonenumber": " 447467",
"userid": 68,
"createdAt": "2020-05-20T06:36:05.997Z",
"updatedAt": "2020-05-20T06:36:05.997Z"
}
]
},
{
"id": 67,
"epprojectname": "DFZeyadavayachatbot",
"username": "Zeyad",
"projectid": "avayachatbot",
"vendorparameters": "{\"synth_speech_cfg\": { \"voice\": { \"name\": \"en-AU-Wavenet-C\"}}}",
"credentials": "1589958578216-AppointmentType.json",
"createdAt": "2020-05-19T15:17:43.399Z",
"updatedAt": "2020-05-20T07:09:38.228Z",
"accountcli": [
{
"id": 249,
"phonenumber": "44433",
"userid": 67,
"createdAt": "2020-05-20T07:09:38.332Z",
"updatedAt": "2020-05-20T07:09:38.332Z"
},
{
"id": 250,
"phonenumber": " 5566",
"userid": 67,
"createdAt": "2020-05-20T07:09:38.332Z",
"updatedAt": "2020-05-20T07:09:38.332Z"
}
]
}
]
The phonenumber field is in AccountCLI model but you added a condition with the field in the Account query.
Try something like this:
if(req.body.phonenumber)
whereStatement['$accountcli.phonenumber$'] = {$like: '%' + req.body.phonenumber + '%'};
I use sequelize orm to manage my data base (mysql).
I make a inner join that work good but the problem that the table that join return a weird variable.
this is my code
const getReports = id => {
return new Promise((resolve, reject) => {
models.Report.findAll({
where: { companyID: [513603324, 515490704, 511493827] },
include: [{
model: models.Reports_type,
attributes:["name"],
required: true
}],
raw: true
})
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
};
The output is
[
{
"id": 8,
"creatorUserID": 1,
"currentUserEditorID": 1,
"companyID": 511493827,
"stageID": 1,
"scenarioID": 1,
"typeID": 1,
"year": 2020,
"deadLine": "2019-10-30T22:00:00.000Z",
"createdAt": "2019-10-29T08:31:19.000Z",
"updatedAt": "2019-10-29T08:31:19.000Z",
"Reports_type.name": "excelent",
"companyName": "energy",
}
]
The problem is i get it weird like this:
"Reports_type.name"
I want the output be:
"name"
This topic has been covered before - see this.
To avoid the prefix, attributes must be specified in the main model rather than the included model. The example below should produce all fields in Report plus Reports_type.name. Note: the alias of Reports_type may be a little different than I've guessed - if you get a "field does not exist", find the correct alias from the generated SQL.
models.Report.findAll({
where: { companyID: [513603324, 515490704, 511493827] },
include: [{
model: models.Reports_type,
attributes:[], // suppress here
required: true
}],
raw: true,
attributes: {
include: [[Sequelize.col("reports_types.name"), "name"]] // include here; table alias may be a little different!
}
})
I have 3 Tables User, Cars and UserCars
User{id, name, phone, email}
Cars{id, name, manufacturer}
UserCars{id, car_id, user_id, role}
User have many cars(through UserCars)
Cars have many users(through UserCars)
I am using express js
router.get('/', async (req, res) => {
try {
let car = await Car.findOne({
where: {
id: req.car_id
}});
let users = await car.getUsers({joinTableAttributes: ['role']})
res.send(users)
} catch (e) {
console.log(e)
res.status(400).send(e)
}
})
and this my response
[
{
"id": 1,
"name": "test",
"email": null,
"phone": null,
"createdAt": "2019-07-09T09:38:11.859Z",
"updatedAt": "2019-07-12T04:34:20.922Z",
"User_car": {
"role": "driver"
}
}
]
but any idea how to include role in the user object, rather then specifying it separately in User_car table,
Is there a way where i can get the below output
[
{
"id": 1,
"name": "test",
"email": null,
"phone": null,
"role": 'driver'
"createdAt": "2019-07-09T09:38:11.859Z",
"updatedAt": "2019-07-12T04:34:20.922Z"
}
]
You can use sequelize.literal to get that field when getting your attributes.
attributtes: [
// define your other fields
[sequelize.literal('`users->User_car`.`role`'), 'role'],
]
Now, I not sure if that is going to work with car.getUsers. I usually do a single query with include and also define the "join" table so I can know how is name it on sequelize. Let me show you an example.
module.exports = (sequelize, DataTypes) => {
const UserCar = sequelize.define('UserCar', {
// id you don't need and id field because this is a N:M relation
role: {
type: DataTypes.STRING
},
carId: {
field: 'car_id',
type: DataTypes.INTEGER
},
userId: {
field: 'user_id',
type: DataTypes.INTEGER
},
}, {
tableName: 'User_car',
underscored: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
});
UserCar.associate = (models) => {
models.user.belongsToMany(models.car, { as: 'cars', through: User_car, foreignKey: 'user_id' });
models.car.belongsToMany(models.user, { as: 'users', through: User_car, foreignKey: 'car_id' });
};
return UserCar;
};
router.get('/', async (req, res) => {
try {
const users = await User.findAll({
include: [{
model: Car,
as: 'cars',
where: { id: req.car_id }
}],
attributtes: [
'id',
'name',
'email',
'phone',
[sequelize.literal('`cars->User_car`.`role`'), 'role'],
]
})
res.send(users)
} catch (e) {
console.log(e)
res.status(400).send(e)
}
});