Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js Sequelize UUID primary key + Postgres

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!

like image 372
Number16BusShelter Avatar asked May 18 '18 15:05

Number16BusShelter


People also ask

Can Postgres generate UUID?

Unfortunately, while PostgreSQL is great for storing and comparing UUID data, it lacks capabilities for creating UUID values in its core. Instead, it relies on third-party modules to create UUIDs using specified techniques.

Is Postgres unique UUID?

UUID is an abbreviation for Universal Unique Identifier defined by RFC 4122 and has a size of 128-bit. It is created using internal algorithms that always generate a unique value.


1 Answers

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);
  }));
like image 77
AbhinavD Avatar answered Oct 20 '22 23:10

AbhinavD