Node.js Sequelize UUID主键+Postgres

9

我尝试使用sequelize创建数据库模型,但是在模型的主键方面遇到了问题。

环境

我在Docker容器中使用Postgres(v10),使用sequelize(Node.js v10.1.0)创建模型并使用GraphQL(0.13.2)+GraphQL-Sequalize(8.1.0)进行请求处理。

问题

在使用sequelize-cli创建模型后,我手动尝试用uuid替换id列。这是我正在使用的模型迁移。

'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');
  }
};

模型:

'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;
};

由于一些问题,Sequalize 执行了下一个表达式:

执行(默认):SELECT "id","uuid","name","ticker","alt_tickers","createdAt","updatedAt" FROM "Currencies" AS "Currency" ORDER BY "Currency"."id" ASC;

这导致出现“列'id'不存在”的错误。

或者,我尝试通过在迁移中将 uuid 列重命名为 id 来修复它:

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

在模型中:
'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;
};

但程序启动时出现了以下错误:

错误:在“Currencies”的属性中添加了名为“id”的列,但未标记为“primaryKey:true”

问题

  • 有没有办法强制sequelize使用UUID作为表的主键而不定义id列?
  • 有没有办法创建不带id列的列?
  • 可能是什么原因导致了这些错误,应该如何修复它?

提前感谢!

2个回答

15

我在网上找到的唯一一份资源,介绍了如何设置UUID列,并使用数据库提供的默认值,而不依赖于第三方uuid npm软件包。具体内容请参考https://krmannix.com/2017/05/23/postgres-autogenerated-uuids-with-sequelize/

简化版:

  1. 您需要使用sqlz迁移安装“uuid-ossp” postgres扩展
  2. 在定义表时,请使用以下defaultValueSequelize.literal('uuid_generate_v4()')

13

你在这里没有发布你的model代码,我认为发生了以下情况:

  1. 数据库已手动从id更改为uuid
  2. 您的模型没有反映出这个更改。

因此,查询正在搜索iduuid

你可以通过像下面这样定义uuid并将其设为主键来解决这个问题。

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);
  }));

1
实际上,模型已经在第一时间更改了。我也尝试回滚到整数“id”,但是数据库中未设置主键。 - Number16BusShelter
当然,请看一下。 - Number16BusShelter
模型仍然显示 id 字段?应该是 uuid。您还应该将其设置为主键 primaryKey: true - AbhinavD
我提供了两个情况。第一个是使用uuid作为UUID数据类型的表格,第二个是使用id作为UUID数据类型的表格,所以先后提供了两个模型。如果我理解你的意思正确,你想要我在迁移中添加主键,但这已经完成了。 - Number16BusShelter
模型和数据库声明主键应该独立并且是推荐的。因此,如果您正在解决“错误:在'Currencies'属性中添加了一个名为'id'的列”,则应该将其作为模型和数据库的主键,因为查询是由Sequelize生成的。 - AbhinavD
好的,现在我明白了。非常感谢。 - Number16BusShelter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接