sequelize: `limit` with `subQuery: false` return wrong result
What are you doing?
Let’s say I have Transaction
model which have many-to-many relation with Good
model. And also belongs to User
model. Here’s my model and relation definition.
module.exports = (sequelize, DataTypes) => {
const Transaction = sequelize.define('Transaction', {
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
autoIncrement: false,
},
userId: {
type: DataTypes.UUID,
allowNull: false,
foreignKey: true,
references: {
model: 'users',
key: 'id',
},
},
status: DataTypes.ENUM('verified', 'waiting', 'empty', 'rejected'),
channel: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {});
Transaction.associate = (models) => {
Transaction.belongsTo(models.User, { as: 'user', foreignKey: 'userId' });
};
return Transaction;
};
module.exports = (sequelize, DataTypes) => {
const Good = sequelize.define('Good', {
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
autoIncrement: false,
},
rphAset: {
type: DataTypes.BIGINT,
allowNull: false,
defaultValue: 0,
},
urUpb: {
type: DataTypes.STRING,
allowNull: false,
},
}, {});
return Good;
};
db.Good.belongsToMany(db.Transaction, { as: 'transactions', through: db.TransactionGood, foreignKey: 'goodId' });
db.Transaction.belongsToMany(db.Good, { as: 'goods', through: db.TransactionGood, foreignKey: 'transactionId' });
I already seed my database with data so user with id 30e1c140-d4d0-4edb-980a-3d7b9a47a958
has 7 transaction. I want to get transaction for that user with all goods in it. Here’s my code.
const x = await models.Transaction.findAll({
subQuery: false,
distinct: true,
where: {
userId: '30e1c140-d4d0-4edb-980a-3d7b9a47a958',
},
include: [
{
model: models.User,
as: 'user',
attributes: ['id','name','createdAt','updatedAt'],
},
{
model: models.Good,
as: 'goods',
},
],
order: [['createdAt','ASC',]],
limit: 10,
});
What do you expect to happen?
It will output array with 7 transcations data (all records in database).
What is actually happening?
It returns array with only 3 data. Here’s generated SQL
SELECT `Transaction`.`id`,
`Transaction`.`userId`,
`Transaction`.`status`,
`Transaction`.`channel`,
`Transaction`.`createdAt`,
`Transaction`.`updatedAt`,
`user`.`id` AS `user.id`,
`user`.`name` AS `user.name`,
`user`.`createdAt` AS `user.createdAt`,
`user`.`updatedAt` AS `user.updatedAt`,
`goods`.`id` AS `goods.id`,
`goods`.`rphAset` AS `goods.rphAset`,
`goods`.`urUpb` AS `goods.urUpb`,
`goods`.`createdAt` AS `goods.createdAt`,
`goods`.`updatedAt` AS `goods.updatedAt`,
`goods->TransactionGood`.`id` AS `goods.TransactionGood.id`,
`goods->TransactionGood`.`createdAt` AS `goods.TransactionGood.createdAt`,
`goods->TransactionGood`.`updatedAt` AS `goods.TransactionGood.updatedAt`,
`goods->TransactionGood`.`goodId` AS `goods.TransactionGood.goodId`,
`goods->TransactionGood`.`transactionId` AS `goods.TransactionGood.transactionId`
FROM `Transactions` AS `Transaction`
LEFT OUTER JOIN `Users` AS `user`ON `Transaction`.`userId` = `user`.`id`
LEFT OUTER JOIN (`TransactionGoods` AS `goods->TransactionGood`
INNER JOIN`Goods` AS `goods` ON `goods`.`id` = `goods->TransactionGood`.`goodId`) ON `Transaction`.`id` = `goods->TransactionGood`.`transactionId`
WHERE `Transaction`.`userId` = '30e1c140-d4d0-4edb-980a-3d7b9a47a958'
ORDER BY `Transaction`.`createdAt` ASC
LIMIT 10;
But when I remove subQuery: false
option it will return 7 data. Here’s generated sql without subQuery: false
option.
SELECT `Transaction`.*,
`user`.`id` AS `user.id`,
`user`.`name` AS `user.name`,
`user`.`createdAt` AS `user.createdAt`,
`user`.`updatedAt` AS `user.updatedAt`,
`goods`.`id` AS `goods.id`,
`goods`.`rphAset` AS `goods.rphAset`,
`goods`.`urUpb` AS `goods.urUpb`,
`goods`.`createdAt` AS `goods.createdAt`,
`goods`.`updatedAt` AS `goods.updatedAt`,
`goods->TransactionGood`.`id` AS `goods.TransactionGood.id`,
`goods->TransactionGood`.`createdAt` AS `goods.TransactionGood.createdAt`,
`goods->TransactionGood`.`updatedAt` AS `goods.TransactionGood.updatedAt`,
`goods->TransactionGood`.`goodId` AS `goods.TransactionGood.goodId`,
`goods->TransactionGood`.`transactionId` AS `goods.TransactionGood.transactionId`
FROM
(SELECT `Transaction`.`id`,
`Transaction`.`userId`,
`Transaction`.`status`,
`Transaction`.`channel`,
`Transaction`.`createdAt`,
`Transaction`.`updatedAt`
FROM `Transactions` AS `Transaction`
WHERE `Transaction`.`userId` = '30e1c140-d4d0-4edb-980a-3d7b9a47a958'
ORDER BY `Transaction`.`createdAt` ASC
LIMIT 10) AS `Transaction`
LEFT OUTER JOIN `Users` AS `user` ON `Transaction`.`userId` = `user`.`id`
LEFT OUTER JOIN (`TransactionGoods` AS `goods->TransactionGood`
INNER JOIN `Goods` AS `goods` ON `goods`.`id` = `goods->TransactionGood`.`goodId`) ON `Transaction`.`id` = `goods->TransactionGood`.`transactionId`
ORDER BY `Transaction`.`createdAt` ASC;
Dialect: mysql Database version: 5.7.18 Sequelize version: 4.38.0 Tested with latest release: Yes
Note : Your issue may be ignored OR closed by maintainers if it’s not tested against latest version OR does not follow issue template.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 3
- Comments: 26 (7 by maintainers)
@papb FYI: In my case the issue takes place, when I include models with @ HasMany relations. I solved my issue by setting “separate” flag to true
Alex
Has there been any progress whatsoever? This is a big deal.
I’ll close this issue as I’ve now documented that
limit
needssubQuery
to betrue
to work properlyIssues related to
$nested.attribute.syntax$
being broken withsubQuery: true
will be sorted out in this thread@fkursun Could you open an issue (if you don’t already have one) with what your query looks like, what the generated SQL is, and what you’d expect it to be?
Related PR to clarify how
limit
works: https://github.com/sequelize/sequelize/pull/13985@chetanmenge @eldadgiladi @Afinetri No solution and workaround for this, the only option is using bare SQL with knex or bookshelf.