skip to Main Content

I’m pretty new to Sequelize and trying to learn all of the cool tricks you can use to format your queries, but have run into a bit of a wall.

Basically I have a table "invoices". I have another table "invoice_items" which has a relationship many invoice_items to one invoice.

Currently I am trying to include this one to many association in a findAll query such that the invoice_items are nested in an array in each invoice object.

Something along the lines of:

[
  {
    name: invoice1
    invoiceItems: [
      itemOne,
      itemTwo,
    ]
  },
    {
    name: invoice2
    invoiceItems: [
      itemOne,
      itemTwo,
    ]
  }
]

When I try this query (essentially grabbed from the documentation)

db.invoice.findAll({
    where: {
        userId: 'ed8fdd40-b807-4e51-b1f5-90fb5b7f6e73'
    },
    include: { all: true, nested: true }
}).then(result => {
    console.log(result)
})

I am met with an error

c:UsersbrendDesktopprojectsinvoice-servernode_modulessequelizelibmodel.js:1189
          let associations = result.get(include.association.as);
                                    ^

TypeError: result.get is not a function
    at c:UsersbrendDesktopprojectsinvoice-servernode_modulessequelizelibmodel.js:1189:37
    at Array.reduce (<anonymous>)
    at c:UsersbrendDesktopprojectsinvoice-servernode_modulessequelizelibmodel.js:1188:50
    at Array.map (<anonymous>)
    at Model._findSeparate (c:UsersbrendDesktopprojectsinvoice-servernode_modulessequelizelibmodel.js:1186:39)
    at invoice.findAll (c:UsersbrendDesktopprojectsinvoice-servernode_modulessequelizelibmodel.js:1153:24)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Node.js v20.10.0

The odd thing is that when I try something like this the query succeeds, but is not formatted as intended (A separate invoice object for each associated invoiceItem)

db.invoice.findAll({
    where: {
        userId: 'ed8fdd40-b807-4e51-b1f5-90fb5b7f6e73'
    },
    include: "invoiceItems",
    raw : true ,
    nest : true
}).then(result => {
    console.log(result)
})

To aid in identifying the issue I will add more full code below (wondering if I have the associations messed up):

invoice model

module.exports = (sequelize, Sequelize, DataType) => {
    const Invoice = sequelize.define('invoice', {
        id: {
         type: DataType.UUID,
         primaryKey: true
        },
        userId: {
         type: DataType.UUID,
         validate: {
            allowNull: false
         }
        },
        name: {
         type: DataType.STRING(150)
        }
//Additional fields left out here for simplicity
     },{
        underscored: true
     });
     Invoice.associate = models => {
      Invoice.hasMany(models.invoiceItem), {
         foreignKey: "invoiceId"
      }
      Invoice.belongsTo(models.user)
     };

     return Invoice
};

invoiceItem model

module.exports = (sequelize, Sequelize, DataType) => {
    const InvoiceItem = sequelize.define('invoiceItem', {
        id: {
         type: DataType.UUID,
         primaryKey: true
        },
        invoiceId: {
         type: DataType.UUID,
         validate: {
            allowNull: false
         }
        },
        userId: {
         type: DataType.UUID,
         validate: {
            allowNull: false
         }
        },
        name: {
         type: DataType.STRING(150)
        }
//Additional fields left out here for simplicity
     },{
        underscored: true
     });
     InvoiceItem.associate = models => {
      InvoiceItem.belongsTo(models.invoice, {
         foreignKey: "invoiceId"
      })
      InvoiceItem.belongsTo(models.user), {
         foreignKey: "userId"
      }};

     return InvoiceItem
};

And finally my index.js file that brings everything together

'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const sequelize = require('../config/database.js')

const db = {}
db.Sequelize = Sequelize;
db.sequelize = sequelize;

fs.readdirSync(__dirname)
  .filter(file => {
    return (
      file.indexOf('.') !== 0 &&
      file !== basename &&
      file.slice(-3) === '.js' &&
      file.indexOf('.test.js') === -1
    );
  })
  .forEach(file => {
    const model = require(path.join(__dirname, file))(db.sequelize, db.Sequelize, db.Sequelize.DataTypes)
    db[model.name] = model;
  });
Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

module.exports = db;

Any thoughts or suggestions are much appreciated, thanks in advance!

2

Answers


  1. Chosen as BEST ANSWER

    In the end I was able to eliminate the error by removing raw: true from the query defaults when I first made the new sequelize instance. Part of the problem seems to be that raw: true work with eager loading. I was then able to use the get() method to unwrap the results into my desired format. More details on the formatting can be found at my related question in case someone finds it helpful at some point.


  2. Your setup appears to be correct so far and the issue might be coming from the options you have specified (nested: true):

    db.invoice.findAll({
        where: {
            userId: 'ed8fdd40-b807-4e51-b1f5-90fb5b7f6e73'
        },
        include: { all: true, nested: true } <------ begin by removing nested: true
    }).then(result => {
        console.log(result)
    })
    

    In the above code, start by removing: nested: true, other options you can look at are plain: true, raw: true etc

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search