Sequelize group by a field which is not selected in attributes - mysql

Here is my query:
await models.advisorCheckModel.findAll({
include: {
model: models.advisorModel,
as: 'advisor',
attributes: [
['advisorFirstName', 'firstName'],
['advisorLastName', 'lastName']
]
},
where: {
userId: user.id,
advisorCheckCreateTime: {
[Op.between]: [startDay, endDay]
}
},
attributes: [
[fn('MIN', col('advisorCheckCreateTime')), 'time'],
// 'advisorId'
],
group: [
[fn('from_unixtime', col('advisorCheckCreateTime'), '%Y-%m-%d %h')],
'advisorId'
],
})
and i got this error:
Column 'advisorId' in group statement is ambiguous
Is there any way to group with advisorId column which is not selected in attributes?

Related

convert sql query to sequelize

I can't convert the query I wrote the sql query to sequelize.
This is the query I want to convert;
SELECT
sum(document_details.qty)'miktar',
stocks.id,
stocks.`name`
FROM
document_details
INNER JOIN documents ON documents.id = document_details.document_id
INNER JOIN stocks ON document_details.stock_id = stocks.id
WHERE documents.warehouse_id = 1
GROUP BY document_details.stock_id
This is the query I wrote. However, I only get one data. The output must come in more than one
const {id} = req.query;
const {limit, page, sortColumn, sortType, search} = req.body;
Documents.hasMany(DocumentsDetail, {foreignKey: "document_id"})
DocumentsDetail.belongsTo(Stocks, {foreignKey: "stock_id"});
const DocumentsList = await Documents.findAll({
limit: limit,
offset: (page - 1) * limit,
order: [
[sortColumn, sortType]
],
where: {
[Op.and]: [
{
warehouse_id: id
},
{
id: {
[Op.substring]: [
search
]
}
},
],
},
include: [
{
model: DocumentsDetail,
attributes: [
"stock_id",
"name",
[sequelize.fn('sum', sequelize.col('qty')), 'total'],
],
group: ["stock_id"]
},
],
});
res.json({
total: total.length,
data: DocumentsList,
warehouse_name
});
How can I fix? Or what is the truth? can you help?
This is how I solved my question. Hope it helps someone else too..
DocumentsDetail.belongsTo(Documents, {foreignKey: "document_id"})
DocumentsDetail.belongsTo(Stocks, {foreignKey: "stock_id"});
await DocumentsDetail.findAll({
attributes: [
[sequelize.fn('sum', sequelize.col('qty')), 'quantity'],
],
where: {
"$document.warehouse_id$": id,
},
include: [
{
model: Documents,
},
{
model: Stocks,
},
],
group: ["stock_id"],
}).then((data) => {
let opt = {
total: data.length,
data: warehouse_name,
warehouse: data
}
res.json(opt);
})

sequelize count associated table rows

Using sequelize and mySQL, I have two tables: User and Post.
Relation between two tables is M : N
db.User.belongsToMany(db.Post, { through: "Likes", as: "Liked" });
db.Post.belongsToMany(db.User, { through: "Likes", as: "Likers" });
What I want is getting post with whole likers id and count of whole likers.
I know how to get whole likers like this.
const post = await Post.findOne({
where: { id: postId },
attributes: ["id", "title", "imageUrl"],
include: [{
model: User,
as: "Likers",
attributes: ["id"],
through: { attributes: [] },
}]
})
// result
{
"id": 36,
"title": "test",
"imageUrl": "하늘이_1644886996449.jpg",
"Likers": [
{
"id": 13
},
{
"id": 16
}
]
}
And, I also know how to get count of whole likers.
const post = await Post.findOne({
where: { id: postId },
attributes: ["id", "title", "imageUrl"],
include: [{
model: User,
as: "Likers",
attributes: [[sequelize.fn("COUNT", "id"), "likersCount"]],
}]
})
// result
{
"id": 36,
"title": "test",
"imageUrl": "하늘이_1644886996449.jpg",
"Likers": [
{
"likersCount": 2
}
]
}
But, I don't know how to get both of them at once.
Check the result when I use both of them.
{
model: User,
as: "Likers",
attributes: ["id", [sequelize.fn("COUNT", "id"), "likersCount"]],
through: { attributes: [] },
}
// result
"Likers": [
{
"id": 13,
"likersCount": 2
}
]
It only shows 1 liker(id: 13)
It must show another liker(id: 16).
What is the problem?
It shows only one because COUNT is an aggregating function and it groups records to count them. So the only way to get both - use a subquery to count records in a junction table while getting records on the other end of M:N relationship.
const post = await Post.findOne({
where: { id: postId },
attributes: ["id", "title", "imageUrl",
// you probably need to correct the table and fields names
[Sequelize.literal('(SELECT COUNT(*) FROM Likes where Likes.postId=Post.id)'), 'LikeCount']],
include: [{
model: User,
as: "Likers",
attributes: ["id"],
through: { attributes: [] },
}]
})

sequelize aggregate group by not working as I want

I want to fetch Votes Info with relations in a group according to audioId, but my code not working as aspected. 'user. id' break the group, and showing one by one vote.
what is the problem with my code? and how to group with only audioId and also fetch related Data
try {
const votes = await globalVotes.findAll({
group: ['audioId', 'mediaType', 'audio.id', 'user.id'],
attributes: [
'audioId',
'mediaType',
[Sequelize.fn('SUM', Sequelize.col('totalVote')), 'total_vote'],
[Sequelize.fn('MAX', Sequelize.col('voterEmail')), 'latest_email'],
[Sequelize.fn('COUNT', Sequelize.col('voteCount')), 'total_vote_count'],
[Sequelize.fn('MAX', Sequelize.col('vottingNum')), 'latest_number'],
[Sequelize.fn('MAX', Sequelize.col('globalVotes.user_Id')), 'latest_user'],
[
Sequelize.fn('MAX', Sequelize.col('globalVotes.updatedAt')),
'latest_time',
],
],
include: [
{
model: Audio,
attributes: ['aTitle', 'aImage', 'audioFolderId'],
include: [
{
model: AudioFolder,
attributes: ['folderName'],
},
],
group: ['audioFolderId.id'],
},
{
model: User,
attributes: ['fullName'],
},
],
order: [[Sequelize.fn('SUM', Sequelize.col('totalVote')), 'DESC']],
raw: true,
nest: true,
});
console.log(votes);
res.status(200).render('admin/chart/audio/index', {
title: 'Manage Audio Votes',
votes,
});
hope i get some info,

How to do where condition on include relation in Loopback

I want to get the result with include relation with where condition on include model.
return this.htcApi.find({
include: [
{
relation: 'nmos',
scope: {
include: 'countries',
},
},
],
where: { name:'Welcome', "nmos.name":'agile'}
});
This where is condition work for name of htc model not for noms module.
I want query like
Select htc.*, nmos.* FROM htc LEFT JOIN nmos ON nmos.id = htc.n_id where htc.name = 'abc' and nmos.name = 'abc';
How can add where condition on the "relation" table?
Simply you need to add where clause in 'scope' object which lies inside the 'include' object. So the code would be like :
return this.htcApi.find({
include: [
{
relation: 'nmos',
scope: {
include: 'countries',
where:{name:'agile'}
},
},
],
where: { name:'Welcome'}
});
In your query, you just need to add the property where within the scope property, like this:
return this.htcApi.find({
include: [
{
relation: 'nmos',
scope: {
include: 'countries',
where: {
and [
{ id: htc.n_id },
{ name: 'abc' },
],
},
},
},
],
where: { name: 'abc' }
});
This should return the htcApi objects named 'abc' with the related nmos objects that have the name 'abc' and the id 'n_id'.

Sequelize include even if it's null

I am using Sequelize express with Node.js as the backend, some data from my sequelize I need to include to another table but some of these data is null so the whole result I’m getting is null.
Question: how can I return some data if data it's available and return the other null if not data is there
router.get("/scheduled/:id", function(req, res, next) {
models.Order.findOne({
where: {
id: req.params.id
},
attributes: ['orderStatus', 'id', 'serviceId', 'orderDescription', 'orderScheduledDate'],
include: [{
model: models.User,
attributes: ['firstName', 'phoneNumber']
}]
}).then(function(data) {
res.status(200).send({
data: data,
serviceName: data["serviceId"]
});
});
});
I want: the result should return null if there is no user for the order and return order details and user when it is null.
However, a where clause on a related model will create an inner join and return only the instances that have matching sub-models. To return all parent instances, you should add required: false for more detail check nested-eager-loading
var users = require('./database/models').user;
models.Order.findOne({
where: {
id: req.params.id
},attributes: ['orderStatus','id','serviceId','orderDescription','orderScheduledDate'],
include: [
{model: users,required: false,
attributes: ['firstName','phoneNumber']
}
]
}).then(function(data) {
res.status(200).send({data : data,serviceName : data["serviceId"]});
});
You can add attribute required: false,
const result = await company.findAndCountAll({
where: conditions,
distinct: true,
include: [
media,
{
model: tag,
where: tagCond,
},
{ model: users, where: userCond, attributes: ['id'] },
{
model: category_company,
as: 'categoryCompany',
where: categoryCond,
},
{ model: media, as: 'logoInfo' },
{ model: city, as: 'city' },
{
model: employee,
as: 'employees',
required: false,
include: [{
model: media,
as: 'avatarInfo',
}],
where: {
publish: {
[Op.ne]: -1,
},
},
},
],
order: [['createdAt', 'DESC']],
...paginate({ currentPage: page, pageSize: limit }),
});