Skip to content
Advertisement

Select All Records with Sequelize ORM when having One-To-Many relationship

I have two tables Users and Shops, User can have multiple shops, and shop can be owned by one user.

I’m using Node.js & Sequelize ORM (postgres)

The Problem

When fetching data from Shop Model, Sequelize add extra field UserId in select query like:

SELECT "id", "userId", "createdAt", "updatedAt", "UserId" FROM "Shops" AS "Shop";

This Query Excecuted when I do:

const shops = await Shop.findAll();

This Line Throws Exception says `error: column “UserId” does not exist’.

StackTrace:

Error
    at Query.run (F:WorkCodingstacknode_modulessequelizelibdialectspostgresquery.js:50:25)
    at F:WorkCodingstacknode_modulessequelizelibsequelize.js:313:28
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async PostgresQueryInterface.select (F:WorkCodingstacknode_modulessequelizelibdialectsabstractquery-interface.js:396:12)
    at async Function.findAll (F:WorkCodingstacknode_modulessequelizelibmodel.js:1119:21)
    at async F:WorkCodingstackapp.js:47:19 {
  name: 'SequelizeDatabaseError',
  parent: error: column "UserId" does not exist
      at Parser.parseErrorMessage (F:WorkCodingstacknode_modulespg-protocoldistparser.js:287:98)
      at Parser.handlePacket (F:WorkCodingstacknode_modulespg-protocoldistparser.js:126:29)
      at Parser.parse (F:WorkCodingstacknode_modulespg-protocoldistparser.js:39:38)
      at Socket.<anonymous> (F:WorkCodingstacknode_modulespg-protocoldistindex.js:11:42)
      at Socket.emit (node:events:390:28)
      at addChunk (node:internal/streams/readable:315:12)
      at readableAddChunk (node:internal/streams/readable:289:9)
      at Socket.Readable.push (node:internal/streams/readable:228:10)
      at TCP.onStreamRead (node:internal/stream_base_commons:199:23) {
    length: 164,
    severity: 'ERROR',
    code: '42703',
    detail: undefined,
    hint: 'Perhaps you meant to reference the column "Shop.userId".',
    position: '50',
    internalPosition: undefined,
    internalQuery: undefined,
    where: undefined,
    schema: undefined,
    table: undefined,
    column: undefined,
    dataType: undefined,
    constraint: undefined,
    file: 'parse_relation.c',
    line: '3599',
    routine: 'errorMissingColumn',
    sql: 'SELECT "id", "userId", "createdAt", "updatedAt", "UserId" FROM "Shops" AS "Shop";',
    parameters: undefined
  },
  original: error: column "UserId" does not exist
      at Parser.parseErrorMessage (F:WorkCodingstacknode_modulespg-protocoldistparser.js:287:98)
      at Parser.handlePacket (F:WorkCodingstacknode_modulespg-protocoldistparser.js:126:29)
      at Parser.parse (F:WorkCodingstacknode_modulespg-protocoldistparser.js:39:38)
      at Socket.<anonymous> (F:WorkCodingstacknode_modulespg-protocoldistindex.js:11:42)
      at Socket.emit (node:events:390:28)
      at addChunk (node:internal/streams/readable:315:12)
      at readableAddChunk (node:internal/streams/readable:289:9)
      at Socket.Readable.push (node:internal/streams/readable:228:10)
    schema: undefined,
    table: undefined,
    column: undefined,
    dataType: undefined,
    constraint: undefined,
    file: 'parse_relation.c',
    line: '3599',
    routine: 'errorMissingColumn',
    sql: 'SELECT "id", "userId", "createdAt", "updatedAt", "UserId" FROM "Shops" AS "Shop";',
    parameters: undefined
  },
  sql: 'SELECT "id", "userId", "createdAt", "updatedAt", "UserId" FROM "Shops" AS "Shop";',
  parameters: {}
}

JavaScript Code

const { Sequelize, Model, DataTypes } = require('sequelize');

const connectToDB = async () => {
    const sequelize = new Sequelize("postgres://postgres:root@localhost:5432/testDB", {
        dialect: 'postgres'
    });
    await sequelize.authenticate();
    console.log('Database connected...');
    return sequelize;
}

connectToDB().then(async (sequelize) => {
    // --- Craete User Model ---
    class User extends Model { }
    await User.init({
        id: {
            primaryKey: true,
            type: DataTypes.UUID,
            defaultValue: Sequelize.UUIDV4,
        }
    }, { sequelize, modelName: 'User' })
    await User.sync();

    // --- Craete Shop Model ---
    class Shop extends Model { }
    await Shop.init({
        id: {
            primaryKey: true,
            type: DataTypes.UUID,
            defaultValue: Sequelize.UUIDV4,
        },
        userId: {
            type: DataTypes.UUID,
            allowNull: false
        }
    }, { sequelize, modelName: 'Shop' })
    await Shop.sync();

    /* RELATION BETWEEN User AND Shop (one-to-many) */
    await User.hasMany(Shop, {
        foreignKey: 'userId',
        onDelete: "CASCADE",
    })
    await Shop.belongsTo(User)

    // --- Find All Shops --
    const shops = await Shop.findAll();
    console.log(shops);

}).catch((err) => console.error(err));

The creation of the tables is Ok as printed in console:

Executing (default): SELECT 1+1 AS result
Executing (default): CREATE TABLE IF NOT EXISTS "Users" ("id" UUID , "createdAt"TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'Users' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): CREATE TABLE IF NOT EXISTS "Shops" ("id" UUID , "userId" UUID NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'Shops' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;

Advertisement

Answer

You need to indicate the same foreignKey option value in both relationships:

/* RELATION BETWEEN User AND Shop (one-to-many) */
    User.hasMany(Shop, {
        foreignKey: 'userId',
        onDelete: "CASCADE",
    })
    Shop.belongsTo(User, {
        foreignKey: 'userId',
    })

P.S. there is no need to indicate await because these are sync functions.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement