Node.js Sequelize UUID primary key + Postgres

graphqlnode.jsormpostgresqlsequelize.js

I try to create database model by using sequelize but I'm facing a problem with model's primary key.

Setting

I'm using Postgres (v10) in docker container and sequalize (Node.js v10.1.0
) for models and GraphQL (0.13.2) + GraphQL-Sequalize (8.1.0) for request processing.

Problem

After creating models by sequelize-cli I've manually tried to replace id column with uuid. Here's my model migration that I'm using.

'use strict';
const DataTypes = require('sequelize').DataTypes;

module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Currencies', {
      uuid: {
        primaryKey: true,
        type: Sequelize.UUID,
        defaultValue: DataTypes.UUIDV4,
        allowNull: false
      },
      name: {
        type: Sequelize.STRING
      },
      ticker: {
        type: Sequelize.STRING
      },
      alt_tickers: {
        type: Sequelize.ARRAY(Sequelize.STRING)
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Currencies');
  }
};

Model:

'use strict';
module.exports = (sequelize, DataTypes) => {
    const Currency = sequelize.define('Currency', {
        uuid: DataTypes.UUID,
        name: DataTypes.STRING,
        ticker: DataTypes.STRING,
        alt_tickers: DataTypes.ARRAY(DataTypes.STRING)
    }, {});
    Currency.associate = function(models) {
        // associations can be defined here
    };
    return Currency;
};

Due to some problem sequalize executes next expression:

Executing (default): SELECT "id", "uuid", "name", "ticker", "alt_tickers", "createdAt", "updatedAt" FROM "Currencies" AS "Currency" ORDER BY "Currency"."id" ASC;

That leads to "column 'id' doesn't exist" error.

Alternatively, I've tried to fix it by renaming uuid column to id at migration:

  ...      
  id: {
      allowNull: false,
      primaryKey: true,
      type: Sequelize.UUID,
      defaultValue: Sequelize.UUIDV4()
  },
  ... 

And at the model:

'use strict';
module.exports = (sequelize, DataTypes) => {
    const Currency = sequelize.define('Currency', {
        id: DataTypes.INTEGER,
        name: DataTypes.STRING,
        ticker: DataTypes.STRING,
        alt_tickers: DataTypes.ARRAY(DataTypes.STRING)
    }, {});
    Currency.associate = function(models) {
        // associations can be defined here
    };
    return Currency;
};

but the result was the following error at the start of the program:

Error: A column called 'id' was added to the attributes of 'Currencies' but not marked with 'primaryKey: true'

Questions

  • So, is there a way to force sequelize to use UUID as the tables primary key without defining id column?
  • Is there a way to create columns without id columns?
  • What possibly caused this errors and how should fix it?

Thanks in advance!

Best Answer

What you have not posted here is your model code. This is what I think has happened

  1. The database has been manually changed from id to uuid.
  2. Your model does not reflect this change.

Hence the query is searching for both id and uuid.

You can fix this my defining uuid in your model like below and making it a primary key

const User = sequelize.define('user', {
  uuid: {
    type: Sequelize.UUID,
    defaultValue: Sequelize.UUIDV1,
    primaryKey: true
  },
  username: Sequelize.STRING,
});

sequelize.sync({ force: true })
  .then(() => User.create({
    username: 'test123'
  }).then((user) => {
    console.log(user);
  }));