question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Sequelize count returns wrong count when association models included

See original GitHub issue

Sequelize count returns wrong count when association models included, in my case, via the model’s defaultScope.

What are you doing?

I have a Post model. The Post model has attachments (oneToMany)

I’m trying to count posts [with attachments] using Sequelize’s count

// Post model
module.exports = (sequelize, DataTypes) => {
  const Post = sequelize.define(
    'Post',
    {
      id: {
        primaryKey: true,
        type: DataTypes.UUID
      },
      title: DataTypes.STRING
    }
  )

  Post.associate = models => {
    Post.hasMany(models.PostAttachment, { as: 'attachments' })

    Post.addScope('defaultScope', {
      include: [
        { model: models.PostAttachment, as: 'attachments' }
      ],
      order: [
        ['id', 'ASC']
      ]
    }, {
     override: true
    })
  }

  return Post
}
// PostAttachment model
module.exports = (sequelize, DataTypes) => {
  const PostAttachment = sequelize.define(
    'PostAttachment',
    {
      id: {
        primaryKey: true,
        type: DataTypes.UUID
      },
      key: DataTypes.STRING
    }
  )

  PostAttachment.associate = models => {
    PostAttachment.belongsTo(models.Post)
  }

  return PostAttachment
}

Sequelize query

const posts = await Post.findAll()
const total = await Post.count()

return { posts, total }

Scenario 1: Single Post, multiple PostAttachments

Posts table

id title createdAt updatedAt
f8d68fc0-48b1-4e90-af73-c9a4dc577461 Title1 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00

PostAttachments table

id key PostId createdAt updatedAt
410819f6-d1c4-44f4-9a52-edbac765e714 Key1 f8d68fc0-48b1-4e90-af73-c9a4dc577461 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00
754ca095-4967-4472-a0f4-1a8e2d761a24 Key2 f8d68fc0-48b1-4e90-af73-c9a4dc577461 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00
754ca095-4967-4472-a0f4-1a8e2d761a25 Key3 f8d68fc0-48b1-4e90-af73-c9a4dc577461 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00

What do you expect to happen?

I’m expecting to get 1 post and total sum 1:

{
  "posts": [{...}],
  "total": 1
}

What is actually happening?

I’m actually getting 1 post and total sum 3:

{
  "posts": [{...}],
  "total": 3
}

Scenario 2: Multiple Posts, multiple PostAttachments

Posts table

id title createdAt updatedAt
f8d68fc0-48b1-4e90-af73-c9a4dc577461 Title1 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00
01a528d2-8696-465f-8739-2b32bc52ceca Title2 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00
01a528d2-8696-465f-8739-2b32bc52cecb Title3 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00

PostAttachments table

id key PostId createdAt updatedAt
410819f6-d1c4-44f4-9a52-edbac765e714 Key1 f8d68fc0-48b1-4e90-af73-c9a4dc577461 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00
754ca095-4967-4472-a0f4-1a8e2d761a24 Key2 f8d68fc0-48b1-4e90-af73-c9a4dc577461 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00
754ca095-4967-4472-a0f4-1a8e2d761a25 Key3 f8d68fc0-48b1-4e90-af73-c9a4dc577461 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00
754ca095-4967-4472-a0f4-1a8e2d761a26 Key4 01a528d2-8696-465f-8739-2b32bc52ceca 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00
754ca095-4967-4472-a0f4-1a8e2d761a27 Key5 01a528d2-8696-465f-8739-2b32bc52ceca 2018-05-23 16:47:09.228000 +00:00 2018-05-23 16:47:09.228000 +00:00

What do you expect to happen?

I’m expecting to get 3 posts and total sum 3:

{
  "posts": [{...}, {...}, {...}],
  "total": 3
}

What is actually happening?

I’m actually getting 3 posts and total sum 6:

{
  "posts": [{...}, {...}, {...}],
  "total": 6
}

I ran a few configurations through. It appears the count calculations are based on each post multiplied by the maximum between 1 and the number of attachments per post, so:

  • PostA * Math.max(1, 3 attachments) = 3
  • PostB * Math.max(1, 2 attachments) = 2
  • PostC * Math.max(1, 0 attachments) = 1

Dialect: postgres Dialect version: XXX Database version: 11.1 Sequelize version: 4.43.0 Tested with latest release: No (If yes, specify that version)

Related: #1517, #9481, #9669, #10239

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:28
  • Comments:16 (1 by maintainers)

github_iconTop GitHub Comments

42reactions
dsmackiecommented, Apr 7, 2019

My solution, which may break other queries but works for my application, is to add a distinct condition. The distinct param is only applied to the count query so it ensures that the correct document count is returned, whilst allowing the internal Sequelize aggregation of associations to continue as intended.

Adding distinct: 'Article.id' to my Article.findAndCountAll query gives me the correct article count.

26reactions
JamesMGreenecommented, Nov 4, 2019

Here’s an enhanced workaround that may not cover every case but hasn’t failed me so far:

// Add a permanent global hook to prevent unknowingly hitting this Sequelize bug:
//   https://github.com/sequelize/sequelize/issues/10557
sequelize.addHook('beforeCount', function (options) {
  if (this._scope.include && this._scope.include.length > 0) {
    options.distinct = true
    options.col = this._scope.col || options.col || `"${this.options.name.singular}".id`
  }

  if (options.include && options.include.length > 0) {
    options.include = null
  }
})

HTH others. 💝

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sequelize findAndCountAll returns wrong count ... - GitHub
What are you doing? I have Post model. Post model has attachment(oneToMany),users(oneToMany), I'm trying to fetch posts with attachments ...
Read more >
Sequelize query returning the wrong number of rows when ...
This works fine if I don't include any associated rows, but when I include the related models it returns 7 rows. I think...
Read more >
Sequelize count associations-postgresql - appsloveworld
I want to count city associations with a table called marker but when i call the code above I have the error above....
Read more >
Eager Loading - Sequelize
As briefly mentioned in the associations guide, eager Loading is the act of querying data of several models at once (one 'main' model...
Read more >
sequelize query use column name instead model name
scope('includeParent').findAndCountAll({ distinct: true }) then the count part generates a wrong query with ambiguous count(DISTINCT("id")) , ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found